Wpf 绑定列表<;列表<;MyClass>&燃气轮机;在网格中创建单元格

Wpf 绑定列表<;列表<;MyClass>&燃气轮机;在网格中创建单元格,wpf,xaml,Wpf,Xaml,以下是我的一篇相关文章中的一些内容: 所以我有一个: List<List<FarmyardSpace>> 列表 我希望它被表示为网格单元格中的按钮。我不能像在相关文章中那样使用UniformGrid,因为我需要定义网格中单元格的大小。理想情况下,我不想在数据中定义行字段和列字段(尽管也许这应该由ViewModel来处理?前几天我刚开始学习这方面的知识,但我仍在关注WPF和MVVM) 下面是我最近的一次尝试,但没有成功(事实上引发了一个异常),在这个特定的示例中,我依

以下是我的一篇相关文章中的一些内容:

所以我有一个:

List<List<FarmyardSpace>>
列表
我希望它被表示为网格单元格中的按钮。我不能像在相关文章中那样使用UniformGrid,因为我需要定义网格中单元格的大小。理想情况下,我不想在数据中定义行字段和列字段(尽管也许这应该由ViewModel来处理?前几天我刚开始学习这方面的知识,但我仍在关注WPF和MVVM)

下面是我最近的一次尝试,但没有成功(事实上引发了一个异常),在这个特定的示例中,我依赖FarmyardSpace上现有的列和行属性:

<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中声明


无论如何,我会感谢任何人帮我解决这个问题,提前谢谢

如果集合项上的属性指定了它们在网格中的位置,那么这显然是最简单的,这就是您现在设置的。如果没有,您可以使用转换器为您计算每个项目的索引,然后将其指定为行/列值,并且在两个维度中的工作方式相同。以下是基本的转换器:

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();
    }
}
<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>
公共类ItemToIndexConverter:IMultiValueConverter
{
公共对象转换(对象[]值,类型targetType,对象参数,CultureInfo区域性)
{
对象项=值。FirstOrDefault();
IList collection=values.OfType().LastOrDefault();
if(集合==null | |项==null)
返回0;
返回集合。索引(项目);
}
公共对象[]转换回(对象值,类型[]目标类型,对象参数,CultureInfo区域性)
{
抛出新的NotImplementedException();
}
}
和修改后的XAML版本(减少到3x3),将当前项和父项控件中的完整集合传递到转换器:

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();
    }
}
<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>

好吧,现在我自己没有得到这个,我并不觉得很糟糕:)这个解决方案对我来说很有意义,但我认为会有一种不太复杂的方法来处理索引,因为这似乎是一件非常基本的事情,我想知道它的布局目的。谢谢你的帮助!