Sunday, May 24, 2009

WPF ListBox Control

I have nearly 4 years of professional experience of the software engineering, In that 4 years I have used nearly all the controls like combo Box, grid view, list view etc controls to is display information to the user but I hardly remember that I have used the List Box control in my any of the project. But now when I am learning the WPF I have used the list box control for the first time and I have found it really cool control regarding the WPF environment. In this post I will discuss the List box control and also the Data Template and the triggers of the control template. Hope you will get some starting point from this post.
For this post I have the customer table in the XML format file and I get data from that file which is place in the DB folder, in the bin directory of the project. The reason for placing the customer table in the XML file is , if any of the user didn't have the sql server then this solution still work form him/her. The goal of this post is to define the layout of the each of the item in the list box item and to display more information regarding one record to display on the list box control. And also to learn about the triggers.

Data Template:
First of all I have define the Data Template for the list box item.DataTemplate are used to specify the visualization of your data objects. DataTemplate objects are particularly useful when you are binding an ItemsControl such as a ListBox to an entire collection. Without specific instructions, a ListBox displays the string representation of the objects in a collection. In that case, you can use a DataTemplate to define the appearance of your data objects. The content of your DataTemplate becomes the visual structure of your data objects. Here is how the output of the list box how its looks like after I have define the data template for the list box item .


Here is the xaml for the Data template of the item template, and I have place the data template for the list box item within the item template area. I have used the grid control and set the columns and the rows of the grid. Next I have added three text block control to display the company name, city and the country of the customer. The text block are displayed in the second column of the grid and I have used the 1, 2 and 3 rows of for the company name, city and the country respectively. The below xaml give the above image output.

<ListBox.ItemTemplate >
<DataTemplate >
<Grid Margin="2,1,2,1" VerticalAlignment="Top" Height="82" >
<Grid.RowDefinitions>
<RowDefinition Height="2"/>
<RowDefinition Height="0.33*"/>
<RowDefinition Height="0.33*"/>
<RowDefinition Height="0.33*"/>
<RowDefinition Height="2"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.05*"/>
<ColumnDefinition Width="0.45*"/>
<ColumnDefinition Width="0.45*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Text="{Binding CompanyName}" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" />
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Center" Text="{Binding City}" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" />
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Top" Text="{Binding Country}" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>

Style And Control Template :
Next I have to set the look of the item of the list box control. For this I have used the style and the control template to set the appearance of the list box item.Windows Presentation Foundation (WPF) styling and templating refer to a suite of features (styles, templates, triggers, and storyboards) that allow designers of an application, document, or user interface (UI) to create visually compelling effects and to standardize on a consistent appearance for their product. Although an author or designer can customize appearance extensively on an application-by-application basis, a strong styling and templating model is necessary to allow maintenance and sharing of the appearance within and among applications. Windows Presentation Foundation (WPF) provides that model.(source). Styles are used to apply common property to more then one element. Below is the code for the style I have used for the list box item, As I want to set common properties for the list box item so I have set the TargetTtype to the ListBoxItem. The common properties such as width, VerticalContentAlignment , Margin, Padding and Foreground color the list box Item. After setting the common properties of the list box items next I have to set the control template for the list box item, to change the appearance and structure of the list box item. For this to change the structure and the appearance of the ListBox item I have set the template property of the style and set the value of the template property.

<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Width" Value="Auto" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Margin" Value="1" />
<Setter Property="Padding" Value="3" />
<Setter Property="Foreground" Value="#FFFFFFFF"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid ShowGridLines="True">
<Grid VerticalAlignment="Top" Height="82" >
<Grid.RowDefinitions>
<RowDefinition Height="2"/>
<RowDefinition Height="0.33*"/>
<RowDefinition Height="0.33*"/>
<RowDefinition Height="0.33*"/>
<RowDefinition Height="2"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.05*"/>
<ColumnDefinition Width="0.45*"/>
<ColumnDefinition Width="0.45*"/>
</Grid.ColumnDefinitions>
<Border Name="brdLeftBorder" Margin="2,2,0,2" Grid.RowSpan="5" CornerRadius="3,0,0,3" Panel.ZIndex="1" Background="{DynamicResource NormalItem}"/>
<Border Margin="0,0,0,0" Grid.Column="1" Grid.ColumnSpan="2" Grid.RowSpan="5" Background="#FF666666" CornerRadius="0,5,5,0" />
<Border Margin="0,0,0,0" Grid.ColumnSpan="3" Grid.RowSpan="5" Background="{x:Null}" BorderThickness="2,2,2,2" BorderBrush="#FF202020" CornerRadius="5,5,5,5" Panel.ZIndex="0"/>
</Grid>
<Grid>
<ContentPresenter />
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="brdLeftBorder" Property="Background" Value="{DynamicResource SelectedItem}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="brdLeftBorder" Property="Background" Value="{DynamicResource MouseOver}" />
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

As you can see in the above example, the ControlTemplate class has a TargetType property that is similar to the TargetType property of the Style class. However, note that unlike Style and DataTemplate, ControlTemplate objects do not have the notion of an implicit key. In other words, if you have a standalone ControlTemplate with the TargetType property set to a type, the ControlTemplate does not get applied to that type automatically. Also note that the TargetType property is required on a ControlTemplate if the template definition contains a ContentPresenter.


After adding the value of the template property of the style above is the look of the listBox item. Now its time to define some user interaction related functionality by using triggers.

Triggers:
In the above code I have used the trigger tag in the control template before closing tag of the control template. I have used two trigger one is the IsSelected and the other one is the IsMouseOver trigger. Trigger are used to applies property values or performs actions conditionally. I have define the Linear gradient brush with the key NormalItem which is of green gradient, MouseOver which is of orange gradient and the SelectedItem which is of blue gradient. And here is the output of the all the three gradients.




In the triggers what I have did is to change the background of the left side border. In the IsSelected trigger I have change the background color of the left side border to the SelectedItem gradient. In the second trigger of the control template which is to change the left border to change to the MouseOver gradient , same property the background property of the target brdLeftBorder is used. One important thing about the trigger is when the condition is no more true of the trigger, say in case of IsMouseOver , when the mouse is out of the item then previous setting are applied. Hope you get some starting point about the control template, data template and the trigger, Send me your suggestion regarding this article, your suggestions are most welcome.

You can download the source code from here.

All and any comments / bugs / suggestions are welcomed!

3 comments:

bradutz01 said...

Hi, at http://www.xamltemplates.net/ you can find themes for all the WPF and Silverlight controls.

bradutz01 said...

Hi, at http://www.xamltemplates.net/ you can find themes for all the WPF and Silverlight controls.

Satya said...

Kudos Asim. Great Job. - Satya