Part 6: Slider for Tile Size
I wanted to add a slider to control a size of the tile. So that user can increase the height/width of the tiles of pictures as shown below.
This was a pretty trivial task since I had used databinding to define the size of each tile. Here are things that were interesting
Here is how the size of the each tile was controlled…
Created a class that represents the size of tile
1: using System;
2: using System.Windows;
3: using System.ComponentModel;
4:
5: namespace Search
6: {
7: /// <summary>
8: /// Class that holds the tile settings. It implements INotifyPropertyChanged
9: /// so that it can be used as a source of databinding
10: /// </summary>
11: public class Tile : INotifyPropertyChanged
12: {
13:
14: #region Public Members
15: //implements INotifyPropertyChanged event
16: public event PropertyChangedEventHandler PropertyChanged;
17:
18: //represents the height of a tile
19: public double TileHeight
20: {
21: get { return _tileheight; }
22: set
23: {
24: _tileheight = value;
25: NotifyPropertyChanged("TileHeight");
26: }
27: }
28:
29: //represents width of a tile
30: public double TileWidth
31: {
32: get { return _tilewidth; }
33: set
34: {
35: _tilewidth = value;
36: NotifyPropertyChanged("TileWidth");
37: }
38: }
39:
40: //represents padding around a tile
41: public Thickness TilePadding
42: {
43: get { return _tilepadding; }
44: set
45: {
46: _tilepadding = value;
47: NotifyPropertyChanged("TilePadding");
48: }
49: }
50: #endregion
51:
52: #region Private Memebers
53:
54: private double _tileheight = 10;
55: private double _tilewidth = 10;
56: private Thickness _tilepadding = new Thickness(5);
57:
58: //fires Property Change event.
59: private void NotifyPropertyChanged(String info)
60: {
61: if (PropertyChanged != null)
62: {
63: PropertyChanged(this, new PropertyChangedEventArgs(info));
64: }
65: }
66: #endregion
67: }
68: }
69:
This class had implemented INotifyPropertyChanged so that it can serve as a data source in two-way binding.
Created a static resource to instantiate the class
This was done so that I can databind to the instance of the class in my markup using Source syntax.
1: <UserControl x:Class="Search.ImageGridView"
2: xmlns="http://schemas.microsoft.com/client/2007"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:control="clr-namespace:Search;assembly=Search"
5: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7: mc:Ignorable="d" d:DesignWidth="295" d:DesignHeight="234" >
8: <UserControl.Resources>
9: <control:ImageSourceConverter x:Key="imagesourceconverter"/>
10: <control:Tile x:Key="TileInfo"/>
11: </UserControl.Resources>
Databind size of image to instance of tile class using source
Since my controls data context was the result returned by live service APIs, I needed to use source syntax to control the property of the tile.
1: <DataTemplate>
2: <Border
3: BorderThickness="2,2,2,2" BorderBrush="#FF313131"
4: CornerRadius="5,5,5,5"
5: Height="{Binding TileHeight, Source={StaticResource TileInfo}}"
6: Width="{Binding TileWidth, Source={StaticResource TileInfo}}"
7: Margin="{Binding TilePadding, Source={StaticResource TileInfo}}"
8: MouseEnter="Border_MouseEnter"
9: MouseLeave="Border_MouseLeave"
10: RenderTransformOrigin="1,1"
11: MouseLeftButtonDown="Border_MouseLeftButtonDown"
12: MouseLeftButtonUp="Border_MouseLeftButtonUp">
13: <Border.RenderTransform>
14: <TransformGroup>
15: <ScaleTransform ScaleX="1" ScaleY="1"/>
16: <SkewTransform AngleX="0" AngleY="0"/>
17: <RotateTransform Angle="0"/>
18: <TranslateTransform X="0" Y="0"/>
19: </TransformGroup>
20: </Border.RenderTransform>
21: <Border.Background>
22: <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
23: <GradientStop Color="#FFFFFFFF"/>
24: <GradientStop Color="#FF71A7BB" Offset="1"/>
25: </LinearGradientBrush>
26: </Border.Background>
27: <Image
28: Source="{Binding Image.ThumbnailURL, Converter={StaticResource imagesourceconverter}}"
29: ImageFailed="Image_ImageFailed"
30: Cursor="Hand" Opacity="0.7"
31: Margin="1,1,1,1"/>
32: </Border>
33: </DataTemplate>
Expose tile properties through APIs on ImageGridView Control
Now consumer of this user control can set the tile size and it will reflect in the view using databinding.
1: //public constructor
2: public ImageGridView()
3: {
4: // Required to initialize variables
5: InitializeComponent();
6: _tileinfo = this.Resources["TileInfo"] as Tile;
7: }
8:
9: //height of each tile
10: public double TileHeight
11: {
12: get { return _tileinfo.TileHeight; }
13: set { _tileinfo.TileHeight = value; }
14: }
15:
16: //width of each tile
17: public double TileWidth
18: {
19: get { return _tileinfo.TileWidth; }
20: set { _tileinfo.TileWidth = value; }
21: }
22:
23: //padding around each tile applied as uniform thickness
24: public Double TilePadding
25: {
26: get { return _tileinfo.TilePadding.Top; }
27: set
28: {
29: //converts double value to uniform thickness value
30: _tileinfo.TilePadding = new Thickness((double)value);
31: }
32: }
Build Slider that controls the size of tiles
Added markup for slider in my ImageGridView control
1: <Slider HorizontalAlignment="Left" Margin="5,0,5,0"
2: VerticalAlignment="Stretch" SmallChange="1"
3: LargeChange="2" Value="5" Grid.Row="0"
4: ValueChanged="Slider_ValueChanged"
5: Width="200" Minimum="1"/>
hooked up the ValueChanged event that changes the size of the tile instance.
1: private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
2: {
3:
4: _tileinfo.TileHeight = _tileinfo.TileHeight * e.NewValue/e.OldValue;
5: _tileinfo.TileWidth = _tileinfo.TileWidth * e.NewValue / e.OldValue;
6: }