WPF动态布局与ItemsControl和Grid [英] WPF Dynamic Layout with ItemsControl and Grid

查看:221
本文介绍了WPF动态布局与ItemsControl和Grid的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我已经创建了一个tic-下面的tac-toe示例表达我的问题:



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

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

表单的DataContext设置为一个实例:

  public class MainViewModel:ViewModelBase 
{
public MainViewModel()
{
Move = new ObservableCollection< MoveViewModel>()
{
new XMoveViewModel(){Row = 0,Column = 0},
new OMoveViewModel(){Row = 1,Column = 0} $ b new XMoveViewModel(){Row = 1,Column = 1},
new OMoveViewModel(){Row = 0,Column = 2},
new XMoveViewModel(){Row = 2,Column = 2 }
};
}
public ObservableCollection< MoveViewModel>移动
{
get;
设置;
}
}

最后,XAML看起来像这样: p>

 < Window.Resources> 
< DataTemplate DataType ={x:Type vm:XMoveViewModel}>
< Image Source =XMove.pngGrid.Row ={Binding Path = Row}Grid.Column ={Binding Path = Column}Stretch =None/>
< / DataTemplate>
< DataTemplate DataType ={x:Type vm:OMoveViewModel}>
< Image Source =OMove.pngGrid.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)中。



发生了什么:



发生了什么http://i48.tinypic.com/29xyl9j.png



所需结果:



所需结果http://i50.tinypic.com/2druhqd.png



所以,我的问题是这样的:我如何在网格中实现我的控件的动态放置?我更喜欢XAML /数据绑定/ MVVM友好的解决方案。



谢谢。



最终代码如下:
http://www.centrolutions.com/downloads/TicTacToe.zip

解决方案

你在正确的轨道上。您只需创建一个 Style 并将其应用于 ItemsControl.ItemContainerStyle 。然后,在样式中,为 Grid.Row Grid.Column 指定一个设置器。 ItemContainerStyle 将适用于为每个项目生成的容器。


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 http://i48.tinypic.com/29xyl9j.png

The desired result:

The desired result http://i50.tinypic.com/2druhqd.png

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.

I have put the final code here: http://www.centrolutions.com/downloads/TicTacToe.zip

解决方案

You're on the right track. You just need to create a Style and apply it to the ItemsControl.ItemContainerStyle. Then, in the style, specify a setter for the Grid.Row and Grid.Column. The ItemContainerStyle will get applied to the containers generated for each item.

这篇关于WPF动态布局与ItemsControl和Grid的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆