Get Microsoft Silverlight

Tuesday, February 03, 2009

A simple Multiselect ComboBox using expression Blend



I have often seen requirements to have a combobox with multiple selection enabled. We know thatWPF ListBox control is having two special properties, which enables the multiple selection but the combobox doesnt have those
public IList SelectedItems { get; }
public SelectionMode SelectionMode { get; set; }
There are many ways we can make a multiselect combo box
1)Create a custom control from the scratch and have a Listbox in the dropdown
2)Extend the combobox and add the above properties to it
3)Edit the Combobox control template to add necessary controls and binding.

I am going to describe the 3rd idea from the above list, which is a total Expression Blend work, so no need of VS2008 to make a multiselect combobox from a simple combobox.

Place a combobox in to the editing area and right click on the control to create an copy of the Control template. Now you can see the Control's tree on the left side of Expression Blend



The ItemPresenter inside the scrollviewer is actually the control which displays the data in the dropdown part of the combobox, we want to havethe multiselection enabled on that. So replace the ItemsPresenter with a ListBox control with SelectionMode=Multiple 
The last control in the tree, ContentPresenter is to show the selectedvalue in the combobox's main area. Since we are going to have more than one value from the ListBox we need to have an ItemsPresenter like control here. Just for simplicity I have replace it with an ItemsControl with a an ItemsPanel as StackPanel with horizontal orientation.
Now we need to bind the ListBox.SelectedItems to the ItemsControl using an ElementName binding.



<Style x:Key="MultiSelectComboBox" TargetType="{x:Type ComboBox}">

<Setter Property="Template">

<Setter.Value>

<ControlTemplate TargetType="{x:Type ComboBox}">

<Grid SnapsToDevicePixels="true" x:Name="MainGrid" Height="Auto" Width="Auto">

<Grid.ColumnDefinitions>

<ColumnDefinition Width="*"/>

<ColumnDefinition Width="0"/>

</Grid.ColumnDefinitions>

<Popup AllowsTransparency="true" IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}"

Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}"

Margin="1" x:Name="PART_Popup" Grid.ColumnSpan="2">

<Border x:Name="DropDownBorder" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding Path=ActualWidth, ElementName=MainGrid}">

<ScrollViewer CanContentScroll="true">

<ListBox x:Name="lstBox" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"

KeyboardNavigation.DirectionalNavigation="Contained" SelectionMode="Multiple" ItemsSource="{TemplateBinding ItemsSource}"/>

</ScrollViewer>

</Border>

</Popup>

<ToggleButton Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Grid.ColumnSpan="2"

  IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{DynamicResource ToggleButtonStyle1}"/>

<ItemsControl IsHitTestVisible="false" ItemsSource="{Binding Path=SelectedItems, ElementName=lstBox}" Margin="4,0,0,0">

<ItemsControl.ItemsPanel>

<ItemsPanelTemplate>

<StackPanel IsItemsHost="True" Orientation="Horizontal"/>

</ItemsPanelTemplate>

</ItemsControl.ItemsPanel>

</ItemsControl>

</Grid>

</ControlTemplate>

</Setter.Value>

</Setter>

</Style>


Now we need to access the SelectedItems from this new control template. Use the bellow line
((ListBox)cmbBox.Template.FindName("lstBox",cmbBox)).SelectedItems
You can download the sample project here

Monday, February 02, 2009

Lilac Chaser - Optical illusion using Silverlight







Get Microsoft Silverlight

"When one stares at the center for about 20 seconds or so, one first sees a gap running around the circle of lilac disks, then a green disk running around the circle of lilac disks, then a green disk running around on the grey background, the lilac disks having disappeared or having been erased by the green disk. This is due to an interesting effect in which the colors of the lilac disks are inverted in the optical illusion to a green color"
This optical illusion is called Lilac chaser . Just thought of creating a silverlight version of this illusion for fun. I have used a radial panel(from my old blog) to layout the ellipses radially, and implemented a a timer to change the visibility in a sequential way.

This kind of effects can be a good candidate for Splash sreen for silverlight applications :)
Full source can be found here