WPF Dynamic Layout with ItemsControl and Grid

Posted by Jason Williams on Stack Overflow See other posts from Stack Overflow or by Jason Williams
Published on 2010-05-26T14:28:59Z Indexed on 2010/05/26 14:31 UTC
Read the original article Hit count: 1727

Filed under:
|
|
|
|

I am creating a WPF form. One of the requirements is that it have a sector-based layout so that a control can be explicitly placed in one of the sectors/cells.

I have created a tic-tac-toe example below to convey my problem:

There are two types and one base type:

public class XMoveViewModel : MoveViewModel
{
}
public class OMoveViewModel : MoveViewModel
{
}
public class MoveViewModel
{
    public int Row { get; set; }
    public int Column { get; set; }
}

The DataContext of the form is set to an instance of:

public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        Moves = new ObservableCollection<MoveViewModel>()
        {
            new XMoveViewModel() { Row = 0, Column = 0 },
            new OMoveViewModel() { Row = 1, Column = 0 },
            new XMoveViewModel() { Row = 1, Column = 1 },
            new OMoveViewModel() { Row = 0, Column = 2 },
            new XMoveViewModel() { Row = 2, Column = 2}
        };
    }
    public ObservableCollection<MoveViewModel> Moves
    {
        get;
        set;
    }
}

And finally, the XAML looks like this:

 <Window.Resources>
    <DataTemplate DataType="{x:Type vm:XMoveViewModel}">
        <Image Source="XMove.png" Grid.Row="{Binding Path=Row}" Grid.Column="{Binding Path=Column}" Stretch="None" />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:OMoveViewModel}">
        <Image Source="OMove.png" Grid.Row="{Binding Path=Row}" Grid.Column="{Binding Path=Column}" Stretch="None" />
    </DataTemplate>
</Window.Resources>
<Grid>
    <ItemsControl ItemsSource="{Binding Path=Moves}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid ShowGridLines="True">
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                </Grid>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</Grid>

What was not so obvious to me when I started was that the ItemsControl element actually wraps each item in a container, so my Grid.Row and Grid.Column bindings are ignored since the images are not directly contained within the grid. Thus, all of the images are placed in the default Row and Column (0, 0).

What is happening:

What is happening

The desired result:

The desired result

So, my question is this: how can I achieve the dynamic placement of my controls in a grid? I would prefer a XAML/Data Binding/MVVM-friendly solution.

Thanks.

© Stack Overflow or respective owner

Related posts about wpf

Related posts about dynamic