Professional, Software

All Search Application Posts So Far…

Wanted to consolidate all search application posts so far

Technorati Tags: ,

https://vivekdalvi.wordpress.com/2008/03/28/part-1-live-search-using-silverlight-main-page/

https://vivekdalvi.wordpress.com/2008/03/29/part-2-live-search-using-silverlight-live-search-call-and-progress/

https://vivekdalvi.wordpress.com/2008/03/30/part-3-image-search-result-view/

https://vivekdalvi.wordpress.com/2008/04/06/part-4-image-detail-view/

https://vivekdalvi.wordpress.com/2008/04/15/part-5-better-image-detail-view/

https://vivekdalvi.wordpress.com/2008/04/21/part-6-slider-for-tile-size/

https://vivekdalvi.wordpress.com/2008/04/22/part-7-web-search-results/

https://vivekdalvi.wordpress.com/2008/04/24/part-8-3d-image-view-using-custom-layout/

https://vivekdalvi.wordpress.com/2008/04/25/part-9-image-size-filter/

Standard
Professional, Software

Part 9: Image Size Filter

This part adds a filtering images out of view using size as the basis. So If user wants to see images bigger than certain size, he could use the slider to do it. This means I needed to convert size into opacity so if the size of image was less than what was set in the slider then I needed to set the opacity of the image. Here is how it looks like when it is running

imagesizefilter

To get to this point, I need to build an IValueConverter implementation that converts size into opacity, which was pretty straight forward.

SizeToOpacityConverter.cs

   1: using System;
   2: using System.Windows.Data;
   3: 
   4: namespace Search
   5: {
   6:     public class SizeToOpacityConverter : IValueConverter
   7:     {
   8:         #region Public Members
   9: 
  10:         public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  11:         {
  12:             Tile tile = (Tile)parameter;
  13:             int imagesize = (int)value/1000;
  14:             if (tile.FilterSize < imagesize)
  15:                 return 1;
  16:             else
  17:                 return 0.2;
  18:         }
  19: 
  20:         public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  21:         {
  22:             return null;
  23:         }
  24:         #endregion
  25:     }
  26: }

ImageGridView.Xaml

   1: <UserControl x:Class="Search.Image3DView"
   2:     xmlns="http://schemas.microsoft.com/client/2007"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:local="clr-namespace:Search;assembly=Search"
   5:     xmlns:control="clr-namespace:MyControls;assembly=MyControls"
   6:     >
   7:     <UserControl.Resources>
   8:         <local:ImageSourceConverter x:Key="imagesourceconverter"/>
   9:
  10:         <local:Tile x:Key="TileInfo"/>
  11:     </UserControl.Resources>
  12:     <ItemsControl ItemsSource="{Binding}">
  13:         <ItemsControl.ItemsPanel>
  14:             <ItemsPanelTemplate>
  15:                 <control:Stack3DPanel FrameCount="5"
  16:                                       MouseLeftButtonDown="Stack3DPanel_MouseLeftButtonDown"/>
  17:             </ItemsPanelTemplate>
  18:         </ItemsControl.ItemsPanel>
  19:         <ItemsControl.ItemTemplate>
  20:             <DataTemplate>
  21:                 <Border
  22:                     BorderThickness="2,2,2,2" BorderBrush="#FF313131"
  23:                     CornerRadius="5,5,5,5"
  24:                     MouseEnter="Border_MouseEnter"
  25:                     MouseLeave="Border_MouseLeave" Background="White">
  26:                     <Border.RenderTransform>
  27:                         <TransformGroup>
  28:                             <ScaleTransform ScaleX="1" ScaleY="1"/>
  29:                             <SkewTransform AngleX="0" AngleY="0"/>
  30:                             <RotateTransform Angle="0"/>
  31:                             <TranslateTransform X="0" Y="0"/>
  32:                         </TransformGroup>
  33:                     </Border.RenderTransform>
  34:                     <Image
  35:                         Margin="5,5,5,5"  Stretch="Uniform"
  36:                         Source="{Binding Image.ImageURL , Converter={StaticResource imagesourceconverter}}"
  37:                         RenderTransformOrigin="0.5,0.5"
  38:                         x:Name="image"
  39:                         HorizontalAlignment="Stretch">
  40:                         <Image.RenderTransform>
  41:                             <TransformGroup>
  42:                                 <ScaleTransform/>
  43:                                 <SkewTransform/>
  44:                                 <RotateTransform/>
  45:                                 <TranslateTransform/>
  46:                             </TransformGroup>
  47:                         </Image.RenderTransform>
  48:                     </Image>
  49:                 </Border>
  50:             </DataTemplate>
  51:         </ItemsControl.ItemTemplate>
  52:     </ItemsControl>
  53: </UserControl>

Second part was the bind the opacity of images with filesize and use above SizeToOpeacityConverter. Interesting part of this xaml is

<Image
   Source="{Binding Image.ThumbnailURL, Converter={StaticResource imagesourceconverter}}"
   Opacity="{Binding Image.ImageFileSize ,
Converter={StaticResource sizetoopacityconverter},
ConverterParameter={StaticResource TileInfo}}"
   ImageFailed="Image_ImageFailed"
   Cursor="Hand"
   Margin="1,1,1,1"/>

Then I hit this problem, which I ended up solving but I am not sure if this is the best way to solve it. If I find it, i will post again later. The problem is that thing that updates in above code is ConverterParameter for the Binding and When parameter changes, I could figure out a way to update a single binding. So I ended up writing this code which actually performance wise was good enough for me but that just seems like a wrong way to do it..

Page.xaml.cs

private voidsizeslider_ValueChanged(objectsender, RoutedPropertyChangedEventArgs<double> e)
{
    strings = e.NewValue.ToString();
    txtvalue.Text = “> ” + s.Split(new char[]{‘.’})[0] + ” (KB)”;
    imageGrid.FilterSize = e.NewValue;
    imageGrid.DataContext = null;
    imageGrid.DataContext = _searchresultcollectioncollection;
}

This basically resets the datacontext and hence all bindings are recomputed.

Here is the copy of working project.

Standard
Professional, Software

Part 8: 3D Image View Using Custom Layout

3D Image View

I think to make view usable, it needs lot more work. But I wanted to build something that could not be easily built using HTML ( and I needed a place to use my stack 3d panel 🙂 ). But here is what it looks like. Getting to this place was pretty easy because I already had a panel that could do this.

 image3dview

Here are few things I used in this…

  1. Custom Panels: Building Custom Layout
  2. ItemsControl: Changing default layout

Building this involved building a user control which has a itemscontrol but instead of using default stackpanel that lays out items vertically, I used stack3dpanel to layout items as if they are in 3d.

Image3DView.xaml

   1: <UserControl x:Class="Search.Image3DView"
   2:     xmlns="http://schemas.microsoft.com/client/2007"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:local="clr-namespace:Search;assembly=Search"
   5:     xmlns:control="clr-namespace:MyControls;assembly=MyControls"
   6:     >
   7:     <UserControl.Resources>
   8:         <local:ImageSourceConverter x:Key="imagesourceconverter"/>
   9:
  10:         <local:Tile x:Key="TileInfo"/>
  11:     </UserControl.Resources>
  12:     <ItemsControl ItemsSource="{Binding}">
  13:         <ItemsControl.ItemsPanel>
  14:             <ItemsPanelTemplate>
  15:                 <control:Stack3DPanel FrameCount="5"
  16:                                       MouseLeftButtonDown="Stack3DPanel_MouseLeftButtonDown"/>
  17:             </ItemsPanelTemplate>
  18:         </ItemsControl.ItemsPanel>
  19:         <ItemsControl.ItemTemplate>
  20:             <DataTemplate>
  21:                 <Border
  22:                     BorderThickness="2,2,2,2" BorderBrush="#FF313131"
  23:                     CornerRadius="5,5,5,5"
  24:                     MouseEnter="Border_MouseEnter"
  25:                     MouseLeave="Border_MouseLeave" Background="White">
  26:                     <Border.RenderTransform>
  27:                         <TransformGroup>
  28:                             <ScaleTransform ScaleX="1" ScaleY="1"/>
  29:                             <SkewTransform AngleX="0" AngleY="0"/>
  30:                             <RotateTransform Angle="0"/>
  31:                             <TranslateTransform X="0" Y="0"/>
  32:                         </TransformGroup>
  33:                     </Border.RenderTransform>
  34:                     <Image
  35:                         Margin="5,5,5,5"  Stretch="Uniform"
  36:                         Source="{Binding Image.ImageURL , Converter={StaticResource imagesourceconverter}}"
  37:                         RenderTransformOrigin="0.5,0.5"
  38:                         x:Name="image"
  39:                         HorizontalAlignment="Stretch">
  40:                         <Image.RenderTransform>
  41:                             <TransformGroup>
  42:                                 <ScaleTransform/>
  43:                                 <SkewTransform/>
  44:                                 <RotateTransform/>
  45:                                 <TranslateTransform/>
  46:                             </TransformGroup>
  47:                         </Image.RenderTransform>
  48:                     </Image>
  49:                 </Border>
  50:             </DataTemplate>
  51:         </ItemsControl.ItemTemplate>
  52:     </ItemsControl>
  53: </UserControl>

The most interesting part of this xaml is

   1: <ItemsControl ItemsSource="{Binding}">
   2:     <ItemsControl.ItemsPanel>
   3:         <ItemsPanelTemplate>
   4:             <control:Stack3DPanel FrameCount="5"
   5:                                   MouseLeftButtonDown="Stack3DPanel_MouseLeftButtonDown"/>
   6:         </ItemsPanelTemplate>
   7:     </ItemsControl.ItemsPanel>

This tells ItemsControl to use my custom panel to layout individual items in the source collection. This control also uses valueconverters for converting URI to source.

Image3DView.xaml.cs

   1: using System;
   2: using System.Windows;
   3: using System.Windows.Input;
   4: using System.Windows.Controls;
   5: using System.Windows.Media;
   6: using System.Windows.Media.Imaging;
   7: using MyControls;
   8: 
   9: namespace Search
  10: {
  11:     public partial class Image3DView : UserControl
  12:     {
  13:         public Image3DView()
  14:         {
  15:             InitializeComponent();
  16:         }
  17: 
  18:         //if iamge fails to load then placeholder image is shown
  19:         private void Image_ImageFailed(object sender, ExceptionRoutedEventArgs e)
  20:         {
  21:             ((Image)sender).Source = new BitmapImage(new Uri("notfound.jpg", UriKind.Relative));
  22:         }
  23: 
  24:         //on mouse enter, increase the size of image and set opacity to 1
  25:         private void Border_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
  26:         {
  27:             //hover effect
  28:             Border b = (Border)sender;
  29:             b.Child.Opacity = 1;
  30:             TransformGroup tg = b.RenderTransform as TransformGroup;
  31:             ScaleTransform st = tg.Children[0] as ScaleTransform;
  32:             st.ScaleX = 1.0;
  33:             st.ScaleY = 1.05;
  34:             b.Background = new SolidColorBrush(Colors.LightGray);
  35:         }
  36: 
  37:         //on mouse leave, reset the size of image and set opacity to 0
  38:         private void Border_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
  39:         {
  40:             //reset hover effect
  41:             Border b = (Border)sender;
  42:             b.Child.Opacity = 0.8;
  43:             TransformGroup tg = b.RenderTransform as TransformGroup;
  44:             ScaleTransform st = tg.Children[0] as ScaleTransform;
  45:             st.ScaleX = 1;
  46:             st.ScaleY = 1;
  47:             b.Background = new SolidColorBrush(Colors.White);
  48:         }
  49: 
  50:         private void Stack3DPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  51:         {
  52:             if (e.Handled == false)
  53:             {
  54:                 ((Stack3DPanel)sender).MoveNext();
  55:             }
  56:         }
  57:     }
  58: }

I also made some changes to Page.xaml and Page.xaml.cs to show this view appropriately. Here is the copy of full working project.

Standard