绑定列表<列表<MyClass>>到网格中的单元格 [英] Binding List&lt;List&lt;MyClass&gt;&gt; to cells in a Grid

查看:19
本文介绍了绑定列表<列表<MyClass>>到网格中的单元格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的一篇相关帖子中的一些背景信息:如何使用不同类型对象的二维数组

Here's some context from a related post of mine: How to databind using to a 2d array of objects of different types

所以我有一个:

List<List<FarmyardSpace>>

我希望将其表示为网格单元格中的按钮.我不能像在相关帖子中那样使用 UniformGrid,因为我需要定义网格中单元格的大小.理想情况下,我不想在我的数据中定义 Row 和 Column 字段(尽管这可能应该由 ViewModel 以某种方式处理?前几天刚开始学习这些东西,我仍然在围绕 WPF 和 MVVM).

I want this to be represented as buttons in cells of a Grid. I can't use UniformGrid as in the related post because I need to define the sizes of the cells in the Grid. Ideally I don't want to have to define Row and Column fields in my data (although perhaps this should be handled by the ViewModel somehow? Just started learning this stuff the other day and I'm still wrapping my head around WPF and MVVM).

这是我的最新尝试,但它不起作用(实际上抛出了异常),在这个特定示例中,我依赖于 FarmyardSpaces 上存在的 Column 和 Row 属性:

Here's my latest attempt which does not work (and in fact throws an exception), and in this particular example I'm relying on Column and Row properties existing on the FarmyardSpaces:

<ItemsControl ItemsSource="{Binding FarmyardGrid}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ItemsControl ItemsSource="{Binding}">
                <ItemsPanelTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="15"/>
                            <RowDefinition />
                            <RowDefinition Height="15"/>
                            <RowDefinition />
                            <RowDefinition Height="15"/>
                            <RowDefinition />
                            <RowDefinition Height="15"/>
                        </Grid.RowDefinitions>
                    </Grid>
                </ItemsPanelTemplate>
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Grid.Row" Value="{Binding Row}"/>
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="15"/>
                    <ColumnDefinition />
                    <ColumnDefinition Width="15"/>
                    <ColumnDefinition />
                    <ColumnDefinition Width="15"/>
                    <ColumnDefinition />
                    <ColumnDefinition Width="15"/>
                    <ColumnDefinition />
                    <ColumnDefinition Width="15"/>
                    <ColumnDefinition />
                    <ColumnDefinition Width="15"/>
                </Grid.ColumnDefinitions>
            </Grid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Grid.Column" Value="{Binding Column}"/>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

我认为这不起作用的部分原因是外部 ItemsControl 包含的项目不是 FarmyardSpaces 而是 List,因此它们没有要绑定到的 Column 属性.我还尝试了内部 ItemsControl 中的 RowDefinitions 和 ColumnDefinitions.这摆脱了异常,但也不起作用,对我来说似乎是错误的,特别是考虑到在相关帖子中使用 UniformGrid 时有效的解决方案,其中列在外部 ItemsControl 中声明.

I think part of the reason this doesn't work is that the Items contained by the outer ItemsControl are not FarmyardSpaces but List, so they don't have a Column property to bind to. I've also tried it with both the RowDefinitions and ColumnDefinitions in the inner ItemsControl. This gets rid of the exception but also doesn't work and seems wrong to me, especially given the solution that works when using UniformGrid in the related post where the Columns are declared in the outer ItemsControl.

无论如何,我很感激任何帮助解决这个问题,提前致谢!

Anyways I'd appreciate any help figuring this out, thanks in advance!

推荐答案

如果您的集合项有属性来指定它们在网格中的位置,这显然是最简单的,这就是您现在的设置.如果没有,您可以使用转换器为您找出每个项目的索引,然后将其分配为行/列值 - 它可以在两个维度上工作相同.这是基本转换器:

If you have properties on your collection items that specify where in the grid they go that's obviously easiest, and that's what you are set up for now. If not, you can use a converter to figure out each item's index for you and then assign that as the Row/Column value - and it can work the same in both dimensions. Here's the basic converter:

public class ItemToIndexConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        object item = values.FirstOrDefault();
        IList collection = values.OfType<IList>().LastOrDefault();

        if (collection == null || item == null)
            return 0;

        return collection.IndexOf(item);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

和您的 XAML 的修改版本(缩减为 3x3)从父项 ItemsControl 获取当前项目和完整集合以传递给转换器:

and modified version of your XAML (cut down to 3x3) getting the current item and the full collection from the parent ItemsControl to pass into the converter:

<ItemsControl ItemsSource="{Binding FarmyardGrid}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ItemsControl ItemsSource="{Binding}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="15"/>
                                <RowDefinition />
                                <RowDefinition Height="15"/>
                            </Grid.RowDefinitions>
                        </Grid>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Grid.Row">
                            <Setter.Value>
                                <MultiBinding>
                                    <MultiBinding.Converter>
                                        <local:ItemToIndexConverter/>
                                    </MultiBinding.Converter>
                                    <Binding/>
                                    <Binding Path="ItemsSource"
                                             RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}"/>
                                </MultiBinding>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="15"/>
                    <ColumnDefinition />
                    <ColumnDefinition Width="15"/>
                </Grid.ColumnDefinitions>
            </Grid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Grid.Column">
                <Setter.Value>
                    <MultiBinding>
                        <MultiBinding.Converter>
                            <local:ItemToIndexConverter/>
                        </MultiBinding.Converter>
                        <Binding/>
                        <Binding Path="ItemsSource"
                                 RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}"/>
                    </MultiBinding>
                </Setter.Value>
            </Setter>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

这篇关于绑定列表<列表<MyClass>>到网格中的单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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