#452 – Data Binding Elements in a Collection to a Grid, Part V

We saw earlier that to bind Grid.Row and Grid.Column properties on child items in an ItemsControl,  we need to set up the binding on the ContentPresenter elements that contain the individual items.

We can do this by overriding the ItemsControl.PrepareContainerForItemOverride method.  This method is called for each item in the collection and receives both the containing element (a ContentPresenter in our case) and the contained item (a ChessPiece object in our example).  We bind the Grid.Row and Grid.Column properties on the ContentPresenter to the same properties on the contained item.

public class GridBasedItemsControl : ItemsControl
    {
        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            base.PrepareContainerForItemOverride(element, item);

            ContentPresenter cp = element as ContentPresenter;

            if ((cp != null) && (item != null))
            {
                BindingOperations.SetBinding(cp, Grid.RowProperty, new Binding { Source = item, Path = new PropertyPath("Row")});
                BindingOperations.SetBinding(cp, Grid.ColumnProperty, new Binding { Source = item, Path = new PropertyPath("Column") });
            }

        }
    }

Everything now works as expected.

NOTE: Reader Bruno pointed out a much better way to do this, using the ItemContainerStyle property.

About Sean
Software developer in the Twin Cities area, passionate about software development and sailing.

6 Responses to #452 – Data Binding Elements in a Collection to a Grid, Part V

  1. Bruno says:

    I have the same effect if I change the item container style like this:

    What do you think about this aproach?

  2. Bruno says:

    I tried, but the xaml didn’t go, sorry…

    Trying again:

    • Bruno says:

      Not again, trying some replacements:

      [Window x:Class=”WpfChess.MainWindow”
      xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
      xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
      Title=”MainWindow” Height=”500″ Width=”500″]
      [Grid]
      [ItemsControl ItemsSource=”{Binding ChessPieces}”]
      [ItemsControl.ItemsPanel]
      [ItemsPanelTemplate]
      [Grid ShowGridLines=”True”]
      [Grid.RowDefinitions]
      [RowDefinition Height=”*”/]
      [RowDefinition Height=”*”/]
      [RowDefinition Height=”*”/]
      [RowDefinition Height=”*”/]
      [RowDefinition Height=”*”/]
      [RowDefinition Height=”*”/]
      [RowDefinition Height=”*”/]
      [RowDefinition Height=”*”/]
      [/Grid.RowDefinitions]
      [Grid.ColumnDefinitions]
      [ColumnDefinition Width=”*”/]
      [ColumnDefinition Width=”*”/]
      [ColumnDefinition Width=”*”/]
      [ColumnDefinition Width=”*”/]
      [ColumnDefinition Width=”*”/]
      [ColumnDefinition Width=”*”/]
      [ColumnDefinition Width=”*”/]
      [ColumnDefinition Width=”*”/]
      [/Grid.ColumnDefinitions]
      [/Grid]
      [/ItemsPanelTemplate]
      [/ItemsControl.ItemsPanel]
      [ItemsControl.ItemTemplate]
      [DataTemplate]
      [Label Content=”{Binding Text}” HorizontalAlignment=”Center” VerticalAlignment=”Center” /]
      [/DataTemplate]
      [/ItemsControl.ItemTemplate]
      [ItemsControl.ItemContainerStyle]
      [Style]
      [Setter Property=”Grid.Row” Value=”{Binding Row}”/]
      [Setter Property=”Grid.Column” Value=”{Binding Column}”/]
      [/Style]
      [/ItemsControl.ItemContainerStyle]
      [/ItemsControl]
      [/Grid]
      [/Window]

      • Bruno says:

        Please replace [ and ] for the correct syntax, this was the only way I could paste the code.

      • Sean says:

        Thanks Bruno! Using ItemContainerStyle is a much better approach, much cleaner. I wrote a new post explaining this method (will be published on 21Dec11) and updated this post to point to it. Thanks again!

Leave a comment