Blog

Books

Books I tech reviewed and recommend
Sorry I can't reply to every email and comment. If you need a fast response, try the WPF Forum or Silverlight Forum.
October 31, 2005

How do I make a data bound Bar Graph?

A very simple bar graph can be created by combining Avalon’s styling and templating features with a data bound ItemsControl. An ItemsControl is simply a control that displays a list of items. Those items can be anything you want: people, numbers, controls, and so on. If you template each item of an ItemsControl to be a rectangle whose height is bound to numerical data, you have a data bound bar graph.

The data source for this sample is a class with a property called ValueCollection of type ObservableCollection. ObservableCollection implements INotifyCollectionChanged, which means that if items are added/removed/replaced from that collection, the binding engine will be notified of that and the UI will be updated.

This is the markup for the ItemsControl:

    <ItemsControl ItemsSource="{Binding Source={StaticResource source}, Path=ValueCollection}" ItemTemplate="{StaticResource template}" Height="130">
        <ItemsControl.ItemsPanel>
            <StackPanel Orientation="Horizontal" />
        </ItemsControl.ItemsPanel>
    </ItemsControl>

The default Panel for ItemsControl has vertical orientation, but we want the items to be displayed horizontally – each bar should be to the right of the previous one. To change the panel, we set the ItemsControl’s ItemsPanel property (see my previous blog post for more details on changing the Panel of an ItemsControl).

The template for each item has a rectangle with height bound to the corresponding integer in the data source and a second rectangle with no fill to add some blank space between the bars:

    <DataTemplate x:Key="template">
        <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom">
            <Rectangle Height="{Binding}" Width="20" Fill="Red" />
            <Rectangle Width="5" />
        </StackPanel>
    </DataTemplate>

This is a very simple bar graph but it will hopefully give you ideas and serve as the base for more elaborate representations of data. This is the result:

Here you can find the VS project with this sample code. This works with September CTP WPF bits.


Posted by Bea under WPF | Comments (15)

October 22, 2005

How do I change the layout of an ItemsControl?

I will show in this sample two ways to change the layout of an ItemsControl. In response to a comment on my previous post, this sample uses XmlDataProvider, which allows binding to XML data.

The easiest way to change the layout of an ItemsControl is simply by setting the ItemsPanel property to the Panel that will contain the items:

    <ListBox ItemsSource="{Binding Source={StaticResource xmlData}}" (…) >
        <ListBox.ItemsPanel>
            <StackPanel Orientation="Horizontal" />
        </ListBox.ItemsPanel>
    </ListBox>

Alternatively, for more extensive customizations, you can create a ControlTemplate. This ControlTemplate allows you to replace the whole VisualTree, including picking a new Panel to hold the items. For example, the following markup shows a ControlTemplate that adds a Border and changes the Panel on the ItemsControl:

    <ControlTemplate x:Key="listBoxTemplate">
        <Border BorderBrush="Orange" BorderThickness="2" Margin="10,0,10,10">
            <StackPanel Orientation="Horizontal" IsItemsHost="True" />
        </Border>
    </ControlTemplate>
        
    <ListBox ItemsSource="{Binding Source={StaticResource xmlData}}" Template="{StaticResource listBoxTemplate}" (…) />

Most people get this far in this scenario, but often forget to set the IsItemsHost property in the Panel. IsItemsHost is a property that says “Use this Panel to lay out the items in the ItemsControl.” Notice that selection still works as usual.

If you want your items to wrap onto multiples lines, you can use a WrapPanel in place of the StackPanel. In this scenario, bear in mind that the default template for ListBox contains a ScrollViewer, so your items won’t wrap. To make them wrap, you can either provide your own ControlTemplate or, if you don’t need selection to work, use an ItemsControl instead of a ListBox.

As I mentioned before, I am using XmlDataProvider to bind to XML data. This is how I converted the GreekGods CLR data source I’ve used in previous samples:

    <Window.Resources>
        <XmlDataProvider XPath="/GreekGods/GreekGod" x:Key="xmlData">
            <GreekGods xmlns="">
                <GreekGod>
                    <Name>Aphrodite</Name>
                    <Description>Goddess of love, beauty and fertility</Description>
                    <RomanName>Venus</RomanName>
                </GreekGod>
                (…)
            </GreekGods>
        </XmlDataProvider>
    </Window.Resources>

The only thing to keep in mind when binding to XML is that instead of using the Path property in the Binding object, you should use the XPath property. You can use either Path or XPath syntax for DisplayMemberPath.

Here you can find the VS project with this sample code. This works with September CTP WPF bits.


Posted by Bea under WPF | Comments (2)

October 15, 2005

What is the difference between SelectedValue and SelectedItem?

When they are used by themselves, these two properties are very similar. The need for both and the difference between the two becomes apparent when SelectedValuePath is also set.

For example, consider our well-known GreekGods data source. I set the DataContext of the StackPanel to be that collection through code:

    GreekGods items;
    items = new GreekGods();
    mainStackPanel.DataContext = items;

And used an empty Binding to bind that collection to the ListBox. I know that I want to select the GreekGod with description “Messenger of the Gods” (even though I am only displaying the Name of each God). This is when SelectedValuePath becomes useful. Each item in the ListBox is a GreekGod object, so by setting SelectedValuePath to “Description” I am able to drill down into the Description property of each GreekGod. Then I just have to set SelectedValue to the description I am looking for and the item becomes selected.

    <StackPanel Name="mainStackPanel">
        <ListBox ItemsSource="{Binding}" DisplayMemberPath="Name" SelectedValue="Messenger of the Gods" SelectedValuePath="Description" Name="listBox1" (…) />
    </StackPanel>

The difference between SelectedValue and SelectedItem should be obvious now. SelectedValue returns the string it was set to (“Messenger of the Gods”), while SelectedItem returns the actual GreekGod object with that description.

    string messengerOfGods = (string)(listBox1.SelectedValue);
    GreekGod hermes = (GreekGod)(listBox1.SelectedItem);

SelectedValue is particularly useful when only part of your item is stored in the model you are data binding to. In this scenario, you would data bind the SelectedValue property to the partial information in your model but the ListBox can show a lot more information about that item.

If you have ideas of how to combine these two properties in one, we would love to hear it.

Here you can find the VS project with this sample code. Put a breakpoint in the handler for the button click to inspect the values of SelectedValue and SelectedItem when the button is clicked. This works with September CTP WPF bits.




Posted by Bea under WPF | Comments (4)

October 3, 2005

New feature in September PDC: DisplayMemberPath

As I’ve shown in previous posts, binding an ItemsControl to an IEnumerable data source is really easy (remember that ListBox and ComboBox derive from ItemsControl). With the introduction of DisplayMemberPath in September PDC, it became even easier for the scenario where you want to display only one property of each data item as text. Before DisplayMemberPath, this scenario required the use of a DataTemplate that would specify the property we’re interested in, like in the following xaml:

    <Window.Resources>
        <DataTemplate x:Key="itemTemplate">
            <TextBlock Text="{Binding Path=Name}" />
        </DataTemplate>
    </Window.Resources>
    
    <ItemsControl ItemsSource="{StaticResource greekGods}" ItemTemplate="{StaticResource itemTemplate}" />

The Data Binding team realized that this was a very common scenario and could be simplified, which was the motivation for introducing the DisplayMemberPath property in ItemsControl. The scenario above can now be done in a single line of xaml:

    <ItemsControl ItemsSource="{StaticResource greekGods}" DisplayMemberPath="Name" />

It’s that easy :)

The image below shows both versions of the ItemsControl, the one on the left is using DataTemplate and the one on the right is using DisplayMemberPath.

Here you can find the VS project with this sample code. This works with September CTP WPF bits.

Update September 18, 2007: Here you can find this project updated with Orcas Beta 2 bits.


Posted by Bea under WPF | Comments (4)