Look Ma! WPF can look like Windows Forms too!
WPF contains many similar controls that you will find in your Windows Forms toolbox. If you really wanted your app to look and feel like Windows Forms, it is quite possible… but why? There are other tools and techniques to provide users (and developers for that matter) with a much richer experience. Use the best tools for the job, and for Rich Internet or Desktop applications today the answer is WPF.
Over the years, many great applications were developed using tools that were available in the day of it’s creation. Cavemen used charred sticks and clay to display great masterpieces on cave walls in order to tell their story, which is in essence a way to display the data they wished to preserve. For the tools they had at their disposal at this time, these displays of data are impressive. The same analogy goes for Windows Forms, I am the first to agree that there are a number of very impressive forms applications out there, for the tools available in Windows Forms these applications are genius! Fast forward to today, while still prominent, Windows Forms isn’t going anywhere soon, but there is a bigger player on the block, which allows designers/developers to work together to display data in a more intuitive fashion and enables a richer user experience above and beyond decoration and animation which is for some reason has been used synonymously when defining WPF. To me the beauty of WPF lies in a very rich data binding model used in conjunction with endless possibilities in data presentation.
Concentrating on the presentation of data, this is the first post in a series that will show some of the power and flexibility behind WPF data binding and Data Templates. Data Templates are used to define the way an object’s data is to be displayed and presented to the user. They can be composed of any number of XAML elements and give you unprecedented power in displaying your data. The posts will contain examples of using a list box control, please keep in mind that the principles shown carry to other data display controls like the combo box and tree view controls.
Displaying a Forms-like list box in WPF
If you require a control that looks and behaves similar to a list box control in Windows Forms, it can be translated simply into using a list box control in WPF without a Data Template. The difference being the DisplayMember property is now the DisplayMemberPath in the WPF list box control and the ValueMember property is now the SelectedValuePath. In the sample below, ImageName and ImageId are both properties of objects being bound to the control. The data being pulled for this sample and all subsequent ones is defined in my previous blog post .
<ListBox Background="AliceBlue" x:Name="lbResults"
DisplayMemberPath="ImageName"
SelectedValuePath="ImageId"
ItemsSource="{StaticResource FavoriteImages}" />
Source code for this plain list box is available here.
A Simple Data Template
While functional, a list box displaying a simple value is not ideal. When binding objects to a control in this way, it leaves it up to the user to deduce whether or not the selection they are choosing is in fact the object they are looking for. In the past, sometimes the Text value is manipulated by appending values of several of the objects properties in order to give the end-user a more informed view of the object they are selecting. A richer experience is required, and this is where Data Templates come into play. Here is a simple example of creating a Data Template which displays multiple properties from the objects being bound, again the data being used in defined in this blog post. Data Templates can be made up of any number of XAML elements, below you see the use of a border around the item, as well as a series of labels in a stack panel whose content (in this case will be rendered as text) is bound to individual object properties of the ImageFavorite class. Think of Data Templates being similar to a repeater control, the template will be repeated for each item(object) being bound:
<ListBox x:Name="lbResults" HorizontalContentAlignment="Stretch"
ItemsSource="{StaticResource FavoriteImages}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Blue" Margin="3" Padding="3"
BorderThickness="2" CornerRadius="5">
<StackPanel>
<Label Content="{Binding ImageName}" FontWeight="Bold" />
<Label Content="{Binding ImageRating}" />
<Label Content="{Binding ImageHref}" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This list box clearly shows multiple properties from the objects being listed and visually separating each item with a rounded blue border. Presenting data in this way gives the user more information about the item that they are selecting. Here is another example of a Simple Data Template that demonstrates the use of some other XAML elements in a Data Template (If you are running the demo code, change the StartupUri window from Window1.xaml to FancierTemplate.xaml in the App.xaml file). The template defined below defines the display of ImageFavorite data using an Image element with a drop shadow, as well as using a Text block and label control.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DockPanel Height="35" Margin="10" Grid.Column="0" Grid.Row="0">
<Border DockPanel.Dock="Top" Background="DarkBlue" CornerRadius="5" >
<TextBlock Text="My Favorite Images" Foreground="White" FontSize="20"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</DockPanel>
<ListBox x:Name="lbResults" Grid.Row="1" Grid.Column="0" Height="240"
HorizontalContentAlignment="Stretch"
ItemsSource="{StaticResource FavoriteImages}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Blue" Margin="3" Padding="3"
BorderThickness="2" CornerRadius="5" Background="Beige">
<StackPanel Orientation="Horizontal">
<Image Margin="10" Width="250" Height="200" Stretch="Fill"
Source="{Binding Path=ImageHref}">
<Image.BitmapEffect>
<DropShadowBitmapEffect />
</Image.BitmapEffect>
</Image>
<StackPanel Orientation="Vertical"
VerticalAlignment="Center">
<TextBlock FontSize="25" Foreground="Goldenrod"
Text="{Binding Path=ImageName}" />
<Label FontSize="18"
Content="{Binding Path=ImageRating}" />
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Sample code for the previous two examples is available here.
Thanks