如何在WPF中将Dictionary<enum, bool>双向绑定到ListView列?

5

我有一个类似这样的类型:

public class EffectViewModel
{
    public string Name { get; set; }
    public string Category { get; set; }

    public Dictionary<ShaderType, bool> ShaderSupport { get; set; }
}

.Name.Category已经绑定到2个单独的列,但ShaderSupport字典没有。

我不知道如何将字典双向绑定到每个ShaderType的单独列。我不知道这些列的数量是否可以动态完成,但我在XAML中对它们进行了硬编码,就像这样:

<GridViewColumn Width="60" Header="GPU" >
<GridViewColumn Width="60" Header="Pixel" >
...

但是现在遇到了绑定部分的问题。有什么想法吗?

你需要在 ShaderSupport = { get; set; } 中移除 = - Justin Morgan
2个回答

3
<ItemsControl Grid.IsSharedSizeScope="True" ItemsSource="{Binding AllEffects}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="NameColumn" />
                        <ColumnDefinition Width="Auto" SharedSizeGroup="CategoryColumn" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Name}" />
                    <TextBlock Text="{Binding Category}" Grid.Column="1" />
                </Grid>
                <ItemsControl ItemsSource="{Binding ShaderSupport}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="60" />
                                </Grid.ColumnDefinitions>
                                <CheckBox Grid.Row="1" IsChecked="{Binding Value, Mode=OneWay}" />
                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

这将创建一个没有标题的网格。为了使复选框以TwoWay模式绑定,需要用自己的类型替换字典,因为KeyValuePair不允许编写Value属性,因此不能用于TwoWay绑定。
请注意,每个EffectVM应该按照相同的顺序在字典中拥有所有着色器。

@Joan,那么您是否需要一个网格,其中行将代表“效果”,列将是“名称,类别,GPU,像素等”? - Snowbear
没错,每个EffectViewModel将使用相同名称的适当属性填充.Name、.Category,并根据每个ShaderType中存储的ShaderSupport值填充GPU、Pixel等列(选中或未选中)。 - Joan Venge
1
@Joan,重写了整个XAML。 - Snowbear
@Joan,使用这段代码,您将不得不自己创建标题 - 只需在根“ItemsControl”上方添加另一个网格即可。 “GridViewColumns”的问题在于我看不到绑定它的方法,尽管可能有某种方法。 - Snowbear
@Snowbear,谢谢。你的解决方案看起来很不错,而且我也不知道GridViewColumns是否支持这个功能。我会尝试像你说的那样在根ItemsControl上面再添加另一个网格。 - Joan Venge
显示剩余6条评论

1

由于字典是可枚举的,因此您可以绑定键和值。 话虽如此,字典的顺序并不总是一致的,因此我会让我的视图模型创建一个包装器 ObservableCollection。

<ListView ItemsSource="{Binding ShaderSupport}">
    <ListView.View>
        <GridView>
            <GridView.Columns>
                <GridViewColumn Width="60" Header="Key" DisplayMemberBinding="{Binding Key}" />
                <GridViewColumn Width="60" Header="Value" DisplayMemberBinding="{Binding Value}" />
            </GridView.Columns>
        </GridView>
    </ListView.View>
</ListView>

1
这将生成一个双列ListView。我认为OP想要多个列,每个ShaderType都在自己的列中。 - itsmatt
是的,我正在尝试在另一个类型中使用ShaderSupport,因为它是用于额外列的。 - Joan Venge
你尝试过使用FrameworkElementFactory吗?它允许以声明式的方式创建数据模板/控件模板。 - Double Down

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