Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to 2-way bind a Dictionary<enum, bool> to a ListView column in WPF?

I have a type like this:

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

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

.Name and .Category is already binded to 2 separate columns, but the ShaderSupport dictionary isn't.

I can't figure out how to 2-way bind the dictionary to a separate column for each ShaderType. I don't know if these number of columns can be done dynamically but I hardcoded them in the xaml, so like:

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

But now stuck on the binding part. Any ideas?

like image 672
Joan Venge Avatar asked Oct 11 '22 15:10

Joan Venge


2 Answers

<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>

This will create a grid without a header. In order to make checkbox bound in TwoWay mode replace dictionary with your own type, KeyValuePair doesn't allow to write Value property and hence cannot be used for TwoWay binding.

Please note that each EffectVM should have all Shaders in the dictionary in the same order.

like image 195
Snowbear Avatar answered Oct 14 '22 08:10

Snowbear


Since dictionary is an IEnumerable you can bind the key and value. That said order is not always consistent with dictionaries so I would have my view model create a wrapper 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>
like image 36
Double Down Avatar answered Oct 14 '22 10:10

Double Down