以下是我的相关帖子的一些背景信息: How to databind using to a 2d array of objects of different types
所以我有一个:
List<List<FarmyardSpace>>
我希望将其表示为网格单元格中的按钮。我不能像在相关帖子中那样使用UniformGrid,因为我需要在Grid中定义单元格的大小。理想情况下,我不想在我的数据中定义行和列字段(虽然这可能是由ViewModel以某种方式处理的?前几天刚刚开始学习这些东西,我仍然围绕着WPF和MVVM)
这是我的最新尝试无效(实际上会引发异常),在这个特定的例子中,我依赖于FarmyardSpaces上存在的Column和Row属性:
<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包含的Items不是FarmyardSpaces而是List,因此它们没有要绑定的Column属性。我也尝试了内部ItemsControl中的RowDefinitions和ColumnDefinitions。这摆脱了异常,但也不起作用,对我来说似乎不对,特别是考虑到在外部ItemsControl中声明Columns的相关帖子中使用UniformGrid时有效的解决方案。
无论如何,我很感激任何帮助解决这个问题,提前谢谢!
答案 0 :(得分:1)
如果您的收藏品上有属性,指明它们在网格中的位置,这显然是最简单的,这就是您现在设置的内容。如果没有,您可以使用转换器为您计算每个项目的索引,然后将其指定为行/列值 - 并且它在两个维度中的工作方式相同。这是基本的转换器:
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获取当前项目和完整集合以传递到转换器:
<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>