WPF ItemsControl Example

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

34 Responses to WPF ItemsControl Example

  1. Dineshrajan says:

    Nice and easy to understand. thanks :)

  2. nelson.rachael.n@gmail.com says:

    Really great article. Thank you for sharing–this really helped. I look forward to reading more of your posts!

  3. Jason says:

    thanks for the sharing, look for more

  4. Batlefieldprince says:

    You are my hero …

  5. jamzc921 says:

    I may be a bit late to the party, but can you send me the source code for this? I’m having a problem with using an ItemsControl with a list of buttons. Nothing seems to be getting displayed, but the buttons are in the collection.

    Thanks!

    • Rachel says:

      I’m not sure what part of the source code you’re looking for. All the XAML is shown already, and all the examples are binding to an ObservableCollection<string> except for the last example, which is binding to an ObservableCollection<MyClass> where MyClass contains 3 properties: Name, ColumnIndex, and RowIndex.

      Perhaps you can post your question on http://www.stackoverflow.com along with your code, and post a link here to the question and I’ll take a look at it.

      • jamzc921 says:

        Well I have an observable collection of a class which has many properties, but I can’t get them to display in an ItemsControl as Buttons. There is apparently something wrong with the binding. I have looked for many answers on the question but to no success. I just wanted to see code behind, but if you say you only have a ObservableCollection of your class then I must be doing something wrong.

  6. sandeep says:

    Thank you very much for your information…

  7. Andy says:

    Very useful article. In the UniformGrid example how does WPF know which cell to put each item in? I’m assuming it’s just “automagic”(!) and the ItemsControl knows how to deal with a UniformGrid, i.e. it puts each item into the next cell?

    • Rachel says:

      A UniformGrid control automatically places each child item in the next available cell, and the Rows and Columns properties can be used to define how many Rows/Columns are available to the Grid.

  8. abra says:

    Thank you very much for your great article.
    Would be possible with this approach to have a canvas containing the ItemControls ? In this case each ItemControl would be a rectangular user control, which has its own width and height (not the same for all ItemControls) and can be positioned on the canvas at a certain x-y coordinate ? I cannot figure out exactly how your sample should be adapted to get this working.

    • Rachel says:

      I’m not sure if I understand your question correctly, however if you’re asking if you can use an ItemsControl to position Items on a Canvas at a specific size and position, then yes you can.

      Simply set the ItemsPanelTemplate to a Canvas object, then bind the Height, Width, Canvas.Top, and Canvas.Left properties of each item in the ItemContainerStyle to position and size each item.

      You’ll need to use bindings for these properties though, because if you set it statically then it will be the same for all items.

      • abra says:

        Thank you for your answer, I think I got it about the item positioning on the canvas.
        The second question would be if it is possible that each ItemControl item represents a wrapper to a user-control with its own view-model and view, which is “switched” using a DataTemplate, as in your article “Switching between Views/UserControls using MVVM”.
        What I would need is a combination ItemControls – DataTemplates, where each ItemControl item could be of a different type. All ItemControls, although different, would have ViewModels/Models derived from a base class which would for instance contain properties like “Name”, “Width”, “Height”, “Canvas.Top” and “Canvas.Left”.
        A UserControl would be for instance a panel with 2 textboxes, another UserControl a panel with a button, a label and a textbox, and so on.

      • Rachel says:

        In the case where you want each item drawn differently based on it’s type, use implicit Data Templates (that’s a DataTemplate with only a TargetType property and no x:Key) in your Window.Resources (or ItemsControl.Resources), and don’t set the ItemTemplate property of your ItemsControl.

        That way, when WPF tries to draw each of your objects in the ItemsControl, it will get drawn using the implicit DataTemplate instead.

      • abra says:

        Thanks again, I will try to write a sample application with implicit Data Templates for ItemsControl, and a Canvas as ItemsPanelTemplate.
        I did not work yet with the ItemsControl, I have first to figure out how to modify my actual application.
        Do you eventually know some links with code samples for the usage of ItemsControl in a MVVM designed application?

  9. abra says:

    Sorry to come back with some more questions …
    In the case of my application, I am not sure if the ItemsSource would be a observable collection of ViewModels (all user controls have the same base ViewModel), which is dynamically filled from code.
    What I am not sure to understand, is how to get an event in the code-behind, when the user control is created, to set programatically the DataContext for the control, and then set the bindings for example for the coordinates and size of the user controls. Also each user control has to bind at initialization different properties of the contained controls (text, colours, …) to properties from their view models.
    Thanks in advance for your help !

    • abra says:

      So, I got my application running with ItemsControl, was not so difficult with your sample in front of my eyes !
      I still have a small problem. I need to perform some actions in the user control, when the corresponding usercontrol view model is dynamically added to or removed from the observable collection which is bound to the ItemsSource property of the ItemsControl (some kind of “Initialization” and “Shutdown” code). For the addition of a new element in the collection I could hook to the DataSource changed event (I added a DependencyProperty in the user control for that), but this event is not triggered when I remove an element form the ItemsSource. Do you eventually have an idea how could the user control be informed when it is removed ?

  10. Finally an easy to understand explanation. Thanks.

  11. Abhishek says:

    Hello Thanks a lot for such a nice article.
    I have one small issue with this.
    Actually i have an expander instead of Textbox or button as showed by you. IT works fine in all case except the last one.
    When i expand the last item, all the items are getting expanded in all the columns. Ideally only the item which i am clicking should expand.

    Reply ASAP.

    Thanks,
    Abhishek

    • Rachel says:

      Hi Abhishek,

      I’m not sure what could be causing that problem without seeing your code, but perhaps you could post your question along with a code sample demonstrating the problem on StackOverflow?

      You will likely find someone able to help you out there

      • Abhishek says:

        Thanks Rachel..! :)
        I got the problem and solution as well..!
        Actually that was happening because of uniform grid used for putting expander, as all the rows of such grid should be of same width. Thats why on click of one item, all the row were getting adjusted to same width.
        So instead of uniform grid now i am using Wrap panel, that solves the problem.

        Regards,
        Abhishek

  12. Mike says:

    How do you add a splitter between each row that is rendered?

    • Rachel says:

      Hi Mike,

      You can’t easily add a Splitter because an ItemsControl wraps each item in a ContentPresenter, and you need the Splitter to be an immediate child of the Grid for it to work correctly.

      You might be able to build a customized ItemsControl class to render Splitters between your ContentPresenters, but I’ve never tried to do this before so wouldn’t know the code for it.

      Perhaps a ListView would suit your needs better?

  13. tanh says:

    Hi Rachel,

    I have question about how to render controls dynamically. It means that i get some data from database, then if value is Text, i will generate TextBox and bind to View (XAML). If value is collection => i will create Combo Box control… So could you help me how to bind these controls to View. Thanks you so much :D

    • Rachel says:

      Hi Tanh,

      Typically I will place my items in a ContentControl, and will use DataTriggers in the ContentControl.Style to change the ContentTemplate based on the object’s type. To check the Object’s Type, I usually use a Converter that accepts a type as the ConverterParameter, and returns True or False if the object matches the type specified in the Parameter. You can view a sample of the sort of code I would use here.

      If you’re having troubles getting that implemented, post a question containing your code on StackOverflow and send me the link to it. I’ll see if I can help out, assuming someone hasn’t already provided you with an answer :)

  14. Vikram says:

    great Article. Thanks a lot for explaining ItemsControl in such an easy way.

  15. RK says:

    Hi Rachel,
    Can we make the Items in Itemscontrol re size independently ie. I have a list of viewmodles that has list of items,If i expand one item it is re sizing all the other items but i dont want that.
    Thnaks,
    RK

    • Rachel says:

      Hi RK,

      That sounds like it has something to do with your ItemTemplate or ItemsPanelTemplate. I’d suggest posting a question on Stack Overflow along with your code to get help with that problem.

  16. Wasim Qadir says:

    For ItemsPanelTemplate, how do you know which button is clicked?

  17. Lewk says:

    Thanks super helpful

  18. Nilupul says:

    Thank you!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 89 other followers

%d bloggers like this: