WPF ItemsControl Example

September 17, 2011

I recently wanted to lookup some ItemsControl examples, and was was quite surprised that my good friend Google was unable to find me any good sites.

So here’s some quick examples using an ItemsControl.

Basic ItemsControl

The basic ItemsControl syntax will look like this:

<ItemsControl ItemsSource="{Binding MyCollection}" />

By default, this will create a Vertical StackPanel, then it will loop through each item in MyCollection, add it to a TextBlock, then add that TextBox to the StackPanel.

Here’s a screenshot of the UI objects that get created, identified with Snoop

The ItemTemplate

Quite often you don’t want to simply display an item as a TextBlock, and that’s where the ItemTemplate comes in.

<ItemsControl ItemsSource="{Binding MyCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding }" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

In this example, I simply changed the TextBlock to a Button, so now when it draws the StackPanel it will draw each item using a Button instead of a TextBlock.

A button is a simple example, however your DataTemplates can be (and frequently are) far more complex than a single element.

The ItemsPanelTemplate

Now suppose you want to display your items in something other than a Vertical StackPanel. That’s where the ItemsPanelTemplate comes in.

<ItemsControl ItemsSource="{Binding MyCollection}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="2" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- ItemTemplate -->
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding }" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

In this case, I’ve replaced our StackPanel with a UniformGrid that has 2 Columns

The ItemContainerStyle

The ItemContainerStyle can be used to modify the style of all items in the ItemsControl, however it does not apply this style to the ItemTemplate item, but rather the ContentPresenter that wraps each item (See Snoop Screenshot above)

For example, if I had used a Grid instead of a UniformGrid, and added a Grid.Row and Grid.Column bindings to my Button, you would find that the items do not show up in the correct Grid cell. If I wanted to set each item in the correct Grid cell, I would need to use the ItemContainerStyle to style the ContentPresenter that wraps each item.

<ItemsControl ItemsSource="{Binding MyCollection}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
            </Grid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- ItemContainerStyle -->
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Column" 
                    Value="{Binding ColumnIndex}" />
            <Setter Property="Grid.Row" 
                    Value="{Binding RowIndex}" />
        </Style>
    </ItemsControl.ItemContainerStyle>

    <!-- ItemTemplate -->
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding Name}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Note: For all the screenshots above I was binding to an ObservableCollection of strings, however for the last one I created a custom class that had 3 properties: Name, ColumnIndex, and RowIndex