Use Styles for an editable Silverlight ComboBox
Sometimes I think reading materials get overlooked in SDKs and we miss some hidden gems. One such gem I’d like to bring to your attention is the ability to add some subtle styling to an AutoCompleteBox from the Silverlight Toolkit to provide you with a cheap version of an editable ComboBox.
Sure Silverlight 2 has a ComboBox as part of the core controls now, but as I’ve previously noted, the ComboBox in current form exhibits only DropDownList behaviors. I’m sure this will likely change with future versions, but if you have a need for an editable ComboBox feel, here’s a start.
If you think about the AutoCompleteBox functionality, it provides a list of items that are filtered when the user starts typing in there. Well, that’s one function of a ComboBox right? The other exhibited behavior we need is to be able to click to activate the DropDownList functionality and select. Here’s where styling comes in (with a little help from some properties on AutoCompleteBox as well).
Let’s start by adding the items we’ll be dealing with: AutoCompleteBox and a data class (I’ll use a local hard-coded data class for portability in this code). To use the AutoCompleteBox, make sure you’ve downloaded the Silverlight Toolkit and then add a reference in your Silverlight project to Microsoft.Windows.Controls.dll. Then add the xmlns decoration in your UserControl…here’s mine (I use “toolkit”):
Here’s the Fruit class I’ll be using:
As you can see it is simple, but I wanted to make sure I was using more than just a string (yes I know essentially it is an object with only a string, but think outside the box :-)). Now we can wire up this code here to get our AutoCompleteBox behavior working:
Here we are using the same ItemFilter method I noted previously about AutoCompleteBox. Once we have this when we start typing we’ll get:
Now all we need to do is make it look and act also like a ComboBox. Here we can take styles and apply them. We’re going to do three things using Style resources:
Now if you look you’ll see that the ToggleButton itself has a Style attribute, so here’s the Style we use for that:
Now the only thing we need to do is add the Style attribute for our AutoCompleteBox as reflected here (notice the added Style attribute):
And now when we look at our application running we have what looks to be an editable ComboBox:
The ComboBox behavior is enabled now via the ToggleButton and the MinimumPrefixLength attribute on the AutoCompleteBox (try changing it to 1 and you’ll see that you don’t get exactly the same behavior).
It’s little gems like this that should cause you to pay attention to the finer details of SDKs, samples, etc. I hope you found this helpful…if you have, please consider subscribing for more samples like this (and no I’m not planning on just emitting all the SDK samples :-)). You can download my code for this above in a complete solution here: ACBEditCombo.zip.
Sure Silverlight 2 has a ComboBox as part of the core controls now, but as I’ve previously noted, the ComboBox in current form exhibits only DropDownList behaviors. I’m sure this will likely change with future versions, but if you have a need for an editable ComboBox feel, here’s a start.
If you think about the AutoCompleteBox functionality, it provides a list of items that are filtered when the user starts typing in there. Well, that’s one function of a ComboBox right? The other exhibited behavior we need is to be able to click to activate the DropDownList functionality and select. Here’s where styling comes in (with a little help from some properties on AutoCompleteBox as well).
Let’s start by adding the items we’ll be dealing with: AutoCompleteBox and a data class (I’ll use a local hard-coded data class for portability in this code). To use the AutoCompleteBox, make sure you’ve downloaded the Silverlight Toolkit and then add a reference in your Silverlight project to Microsoft.Windows.Controls.dll. Then add the xmlns decoration in your UserControl…here’s mine (I use “toolkit”):
1: <UserControl x:Class="ACBEditCombo.Page"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:toolkit="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"
5: Width="400" Height="300">
6: <Grid x:Name="LayoutRoot" Background="White">
7: <toolkit:AutoCompleteBox MinimumPrefixLength="0"
8: MinimumPopulateDelay="200"
9: x:Name="FruitChoice"
10: Width="200" Height="25" />
11: Grid>
12: UserControl>
1: #region Fruit Class
2: public class Fruit
3: {
4: public string Name { get; set; }
5: public override string ToString()
6: {
7: return this.Name;
8: }
9:
10: public static ListGetFruitChoices()
11: {
12: Listchoices = new List ();
13:
14: choices.Add(new Fruit() { Name = "Apple" });
15: choices.Add(new Fruit() { Name = "Apricot" });
16: choices.Add(new Fruit() { Name = "Banana" });
17: choices.Add(new Fruit() { Name = "Orange" });
18: choices.Add(new Fruit() { Name = "Pineapple" });
19: choices.Add(new Fruit() { Name = "Mango" });
20: choices.Add(new Fruit() { Name = "Papaya" });
21: choices.Add(new Fruit() { Name = "Pumpkin" });
22:
23: return choices;
24: }
25: }
26: #endregion
1: public partial class Page : UserControl
2: {
3: Listchoices = Fruit.GetFruitChoices();
4:
5: public Page()
6: {
7: InitializeComponent();
8: Loaded += new RoutedEventHandler(Page_Loaded);
9: }
10:
11: void Page_Loaded(object sender, RoutedEventArgs e)
12: {
13: FruitChoice.ItemsSource = choices;
14: FruitChoice.ItemFilter = (prefix, item) =>
15: {
16: if (string.IsNullOrEmpty(prefix))
17: {
18: return true;
19: }
20:
21: Fruit f = item as Fruit;
22:
23: if (f == null)
24: {
25: return false;
26: }
27:
28: return f.Name.ToLower().Contains(prefix.ToLower());
29: };
30: }
31: }
Now all we need to do is make it look and act also like a ComboBox. Here we can take styles and apply them. We’re going to do three things using Style resources:
- Modify the control template for our toolkit:AutoCompleteBox to include a ToggleButton
- Create a style for the ToggleButton that looks like an arrow to cue the user what to do with it
- Style the list displayed a little bit
1: <Style x:Key="EditableComboStyle" TargetType="toolkit:AutoCompleteBox">
2: <Setter Property="SearchMode" Value="StartsWith" />
3: <Setter Property="Background" Value="#FF1F3B53"/>
4: <Setter Property="IsTabStop" Value="False" />
5: <Setter Property="HorizontalContentAlignment" Value="Left"/>
6: <Setter Property="BorderBrush">
7: <Setter.Value>
8: <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
9: <GradientStop Color="#FFA3AEB9" Offset="0"/>
10: <GradientStop Color="#FF8399A9" Offset="0.375"/>
11: <GradientStop Color="#FF718597" Offset="0.375"/>
12: <GradientStop Color="#FF617584" Offset="1"/>
13: LinearGradientBrush>
14: Setter.Value>
15: Setter>
16: <Setter Property="Template">
17: <Setter.Value>
18: <ControlTemplate TargetType="toolkit:AutoCompleteBox">
19: <Grid Margin="{TemplateBinding Padding}">
20: <VisualStateManager.VisualStateGroups>
21: <VisualStateGroup x:Name="PopupStates">
22: <VisualStateGroup.Transitions>
23: <VisualTransition GeneratedDuration="0:0:0.1" To="PopupOpened" />
24: <VisualTransition GeneratedDuration="0:0:0.2" To="PopupClosed" />
25: VisualStateGroup.Transitions>
26: <VisualState x:Name="PopupOpened">
27: <Storyboard>
28: <DoubleAnimation Storyboard.TargetName="PopupBorder" Storyboard.TargetProperty="Opacity" To="1.0" />
29: Storyboard>
30: VisualState>
31: <VisualState x:Name="PopupClosed">
32: <Storyboard>
33: <DoubleAnimation Storyboard.TargetName="PopupBorder" Storyboard.TargetProperty="Opacity" To="0.0" />
34: Storyboard>
35: VisualState>
36: VisualStateGroup>
37: VisualStateManager.VisualStateGroups>
38: <TextBox IsTabStop="True" x:Name="Text" Style="{TemplateBinding TextBoxStyle}" Margin="0" />
39: <ToggleButton
40: x:Name="DropDownToggle"
41: HorizontalAlignment="Right"
42: VerticalAlignment="Center"
43: Style="{StaticResource ComboToggleButton}"
44: Margin="0"
45: HorizontalContentAlignment="Center"
46: Background="{TemplateBinding Background}"
47: BorderThickness="0"
48: Height="16" Width="16"
49: >
50: <ToggleButton.Content>
51: <Path x:Name="BtnArrow" Height="4" Width="8" Stretch="Uniform" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "
52: Margin="0,0,6,0" HorizontalAlignment="Right">
53: <Path.Fill>
54: <SolidColorBrush x:Name="BtnArrowColor" Color="#FF333333"/>
55: Path.Fill>
56: Path>
57: ToggleButton.Content>
58: ToggleButton>
59: <Popup x:Name="Popup">
60: <Border x:Name="PopupBorder" HorizontalAlignment="Stretch" Opacity="0.0" BorderThickness="0" CornerRadius="3">
61: <Border.RenderTransform>
62: <TranslateTransform X="2" Y="2" />
63: Border.RenderTransform>
64: <Border.Background>
65: <SolidColorBrush Color="#11000000" />
66: Border.Background>
67: <Border HorizontalAlignment="Stretch" BorderThickness="0" CornerRadius="3">
68: <Border.Background>
69: <SolidColorBrush Color="#11000000" />
70: Border.Background>
71: <Border.RenderTransform>
72: <TransformGroup>
73: <ScaleTransform />
74: <SkewTransform />
75: <RotateTransform />
76: <TranslateTransform X="-1" Y="-1" />
77: TransformGroup>
78: Border.RenderTransform>
79: <Border HorizontalAlignment="Stretch" Opacity="1.0" Padding="2" BorderThickness="2" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="3">
80: <Border.RenderTransform>
81: <TransformGroup>
82: <ScaleTransform />
83: <SkewTransform />
84: <RotateTransform />
85: <TranslateTransform X="-2" Y="-2" />
86: TransformGroup>
87: Border.RenderTransform>
88: <Border.Background>
89: <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
90: <GradientStop Color="#FFDDDDDD" Offset="0"/>
91: <GradientStop Color="#AADDDDDD" Offset="1"/>
92: LinearGradientBrush>
93: Border.Background>
94: <ListBox x:Name="SelectionAdapter" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" ItemTemplate="{TemplateBinding ItemTemplate}" />
95: Border>
96: Border>
97: Border>
98: Popup>
99: Grid>
100: ControlTemplate>
101: Setter.Value>
102: Setter>
103: Style>
1: <Style x:Name="ComboToggleButton" TargetType="ToggleButton">
2: <Setter Property="Foreground" Value="#FF333333"/>
3: <Setter Property="Background" Value="#FF1F3B53"/>
4: <Setter Property="Padding" Value="0"/>
5: <Setter Property="Template">
6: <Setter.Value>
7: <ControlTemplate TargetType="ToggleButton">
8: <Grid>
9: <Rectangle Fill="Transparent" />
10: <ContentPresenter
11: x:Name="contentPresenter"
12: Content="{TemplateBinding Content}"
13: ContentTemplate="{TemplateBinding ContentTemplate}"
14: HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
15: VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
16: Margin="{TemplateBinding Padding}"/>
17: Grid>
18: ControlTemplate>
19: Setter.Value>
20: Setter>
21: Style>
1: <UserControl x:Class="ACBEditCombo.Page"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:toolkit="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"
5: Width="400" Height="300">
6: <Grid x:Name="LayoutRoot" Background="White">
7: <toolkit:AutoCompleteBox MinimumPrefixLength="0"
8: MinimumPopulateDelay="200"
9: x:Name="FruitChoice"
10: Width="200" Height="25"
11: Style="{StaticResource EditableComboStyle}"/>
12: Grid>
13: UserControl>
The ComboBox behavior is enabled now via the ToggleButton and the MinimumPrefixLength attribute on the AutoCompleteBox (try changing it to 1 and you’ll see that you don’t get exactly the same behavior).
It’s little gems like this that should cause you to pay attention to the finer details of SDKs, samples, etc. I hope you found this helpful…if you have, please consider subscribing for more samples like this (and no I’m not planning on just emitting all the SDK samples :-)). You can download my code for this above in a complete solution here: ACBEditCombo.zip.
Use Styles for an editable Silverlight ComboBox
Reviewed by BloggerSri
on
11:23 AM
Rating:
No comments:
Post a Comment