WPF使用ItemsControl和Grid进行动态布局

35

我正在创建一个 WPF 表单,其中一个要求是它具有基于扇区的布局,以便可以将控件明确放置在其中一个扇区/单元格中。

下面是我创建的井字棋示例,以传达我的问题:

有两种类型和一个基础类型:

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

表单的DataContext被设置为一个实例:
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;
    }
}

最后,XAML看起来像这样:

 <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>

当我开始时,对我来说不太明显的是,ItemsControl元素实际上将每个项包装在一个容器中,因此我的Grid.Row和Grid.Column绑定被忽略了,因为图像并不直接包含在网格中。因此,所有的图像都放置在默认的行和列(0,0)。

正在发生的事情:

What is happening

所需结果:

The desired result

所以,我的问题是:我如何在网格中实现控件的动态放置?我希望有一个XAML / Data Binding / MVVM友好的解决方案。
谢谢。
我已经将最终代码放在这里: http://www.centrolutions.com/downloads/TicTacToe.zip

嗨,Jason, 有没有可能拿到你的井字棋的完整代码?我很想看看。谢谢! - VitalyB
2
不幸的是,该项目只是一个例子,而不是一个完全功能的游戏。这是一个更大的(非井字棋)项目的原型。如果您仍然感兴趣,我已经在原始问题下方放置了最终代码的链接。 - Jason Williams
2
这是一个非常好的问题和答案 - 非常感谢您发布最终代码链接!它确实帮助了我很多。 - Guy Starbuck
源代码是MVVM的一个很好的例子。真的很快地指引了我正确的方向! - eselk
非常感谢您指出了ItemsControl.ItemContainerStyle,它允许配置行和列,解决了我的问题!我创建了一个用户控件,其中包含一个10x10的圆形,用于表示咖啡应用程序的表格布局。 - yancyn
1个回答

29

你已经在正确的轨道上了。你只需要创建一个Style并将其应用到ItemsControl.ItemContainerStyle中。然后,在样式中,指定Grid.RowGrid.Column的属性值即可。ItemContainerStyle将会被应用到为每个项生成的容器上。


啊哈!我知道我漏掉了什么。谢谢你的帮助。那个方法很好用。 - Jason Williams
1
我正在尝试在Silverlight中做完全相同的事情,有人知道如何做吗?(ItemContainerStyle在Silverlight中不可用...) - Emil Badh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接