Monday, January 14, 2013

WPF ListBox Control DataTemplate

How to modify a WPF ListBox control template?

The WPF ListBox control is a simple list type view control that enumerates all the items from the items source and display it in the User Interface. This is a one way to simplify the display of multiple items with dynamic capability.

Below shows the actual WPF ListBox control (default style and template) inside a window.



You'll see the control displayed 7 items (company name) since I actually pre-loaded the item source of the control. In order for you not to confuse, I'll explain the classes I used in binding and how did I loaded the items into the ListBox.

Image below is my current solution. I added a new folder that contains a logo for the company listed above and set each item Build Action property to be a Resource.



In my ListBox Window, I added the code below.


<Window x:Class="CodesDirectory.ListBox"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ListBox" Height="300" Width="300">
    <Grid>
        <ListBox Name="listBox" DisplayMemberPath="Name" Margin="5"></ListBox>
    </Grid>
</Window>


In my Window code behind, below is the code.


public ListBox()
{
    InitializeComponent();
    this.LoadLogos();
}


private void LoadLogos()
{
    this.listBox.Items.Add(new CompanyDataContext("Adobe", "Adobe is a designing tool.", "/Company Logos/adobe.jpg"));
    this.listBox.Items.Add(new CompanyDataContext("Facebook", "FedEx is a social networking website.", "/Company Logos/facebook.jpg"));
    this.listBox.Items.Add(new CompanyDataContext("FedEx", "FedEx is a courier company.", "/Company Logos/fedex.jpg"));
    this.listBox.Items.Add(new CompanyDataContext("Golden Gate", "Golden gate is a financial company focusing on stock exchange.", "/Company Logos/golden gate.jpg"));
    this.listBox.Items.Add(new CompanyDataContext("Onitsuka Tiger", "A shoe company originated from Japan.", "/Company Logos/onitsuka tiger.jpg"));
    this.listBox.Items.Add(new CompanyDataContext("Twitter", "Twitter is a micro blogging website.", "/Company Logos/twitter.jpg"));
    this.listBox.Items.Add(new CompanyDataContext("Vans", "Vans is a shoe company for the skaters.", "/Company Logos/vans.jpg"));
}

Now, what is the CompanyDataContext object? It is a custom Type I made to host the values I want to be displayed in the ListBox. In short, this is a DataContext. Once you added this object manually into the ListBox  then each item you see in the ListBox is now a CompanyDataContext object (you can cast and get the property everytime you iterate or reference it).

Note: One important property in ListBox when you're binding an object is DisplayMemberPath. This define what field of the object are you going to display in every item visible in the ListBox .

Below is the actual class.


private class CompanyDataContext
{
    public CompanyDataContext(string name, string about, string image)
    {
        this.Name = name;
        this.About = about;
        this.Image = image;
    }

    public string Name { get; private set; }

    public string About { get; private set; }

    public string Image { get; private set; }
}

Now since I already defined the basic needs, let us go to templating part.

Customize WPF ListBox control template

One important property you need to do when styling is the ItemContainerStyle property of the ListBox control. This property is used when designing each of the item of the ListBox, or how are you going to customized the display of each item.

Another property that is common in used is the DateTemplate. This property is used how are you going to override the existing template used by the default ListBoxItem style when binding a data object. This is usable when you only would like to override the Template and not the Style.

In my case, I will only use the DataTemplate and later will discuss how to modify the actual style.



Image above only used the DataTemplate to design how are you going to display the individual item in the ListBox control. To implement this, you need to create a new ResourceDictionary object and reference it to your Window (or the parent container of your ListBox).

Sample ResourceDictionary for the ListBox.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   
    <DataTemplate x:Key="templateListBoxItem">
        <Grid Margin="5">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <Border Grid.Column="0"
                    Grid.Row="0"
                    Grid.RowSpan="2"
                    Margin="0,0,10,0">
                <Image Source="{Binding Path=Image}"
                       Stretch="Fill"
                       Height="40"
                       Width="40"></Image>
            </Border>
            <TextBlock Text="{Binding Path=Name}"
                       FontWeight="Bold"
                       Grid.Column="1"
                       Grid.Row="0"></TextBlock>
            <TextBlock Text="{Binding Path=About}"
                       Grid.Column="1"
                       Grid.Row="1"></TextBlock>
        </Grid>
    </DataTemplate>
   
    <Style x:Key="styleListBox" TargetType="{x:Type ListBox}">
        <Setter Property="ItemTemplate" Value="{StaticResource ResourceKey=templateListBoxItem}"></Setter>
    </Style>

</ResourceDictionary>

Above ResourceDictionary object only contains the data template named templateListBoxItem and a style named styleListBox. Reference and apply it to your ListBox.

Go back to your ListBox window and add this at the top.


<Window.Resources>
     <ResourceDictionary Source="/Styles/ListBox.xaml"></ResourceDictionary>
</Window.Resources>

Once added, set the style of your ListBox by using the DynamicResource binding.

<ListBox Name="listBox"
         DisplayMemberPath="Name"
         Margin="5"
         Style="{DynamicResource ResourceKey=styleListBox}">
</ListBox>

And that's it. Please visit this link how to modify the ListBox style.

1 comment:

Place your comments and ideas