Oct 22, 2005

How to 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.

2 Comments
  1. Anonymous

    Is there any chance you could update these cool old samples to the June CTP? I’m new to WPF and having be struggling for a week with the fact that most examples simply do not work with the June CTP.

    I changed the namespaces on this example, and in XamlPad is simply says “Object reference not set to an instance of an object” without any line number reference.

    • Bea

      The syntax for this sample in particular changed a lot with newer bits – we had a big breaking change. I updated the July CTP version of this sample here.

      If anyone has trouble updating other samples in this blog, I will be happy to convert them to more recent bits.

      Thanks,
      Bea

Comments are closed.