如何在一个列表框中使用多个字典

本文关键字:字典 列表 一个 | 更新日期: 2023-09-27 18:05:01

我想知道是否有可能在列表框数据模板中使用两个字典。我想在文本框中使用Names的值,在复选框中使用EnabledNames的值。这可能吗?如果是这样,我该怎么做呢?

一些示例数据将是:

Dictionary<string, string> Names = new Dictionary<string, string>()
            {
                { "4EG25","John" },
                {"923OT", "Joe" }
            };
            Dictionary<string, bool> EnabledNames = new Dictionary<string, bool>()
            {
                { "4EG25",false },
                {"923OT", true}
            };

以及我想如何使用的方式:

<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="359" VerticalAlignment="Top" Width="673" Margin="0,0,-0.333,-0.333" ItemsSource="{Binding Path=Names, Mode=OneWay}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <CheckBox IsChecked="{Binding Path=EnabledNames[ItemsSource.Key].Value}" />
                                    <TextBlock Text="{Binding Path=ItemsSource.Value}"/>
                                </StackPanel>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>

如何在一个列表框中使用多个字典

创建一个包含这两个值的类,并将其用作ItemsSource

class Name
{
    public string Value { get; set; }
    public bool Enabled { get; set; }
}
public IEnumerable<Name> TheNames
{
    get { return Names.Select(n => new Name {Value = n.Value, Enabled = EnabledNames[n.Key]}); }
}

<ListBox ItemsSource="{Binding Path=TheNames, Mode=OneWay}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding Path=Enabled}" />
                <TextBlock Text="{Binding Value}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

这是非常困难的,所以我建议您为您的ListBox创建特定的类DataContext。

你可以试试你的情况:

  1. WPF绑定只能做到属性(你的字典现在是字段,所以你的绑定将无法工作。你的ViewModel可以是这样的:

    public class ViewModel
    {
        public ViewModel()
        {
            Names = new Dictionary<string, string>()
            {
                { "4EG25","John" },
                {"923OT", "Joe" }
            };
            EnabledNames = new Dictionary<string, bool>()
            {
                { "4EG25",false },
                {"923OT", true}
            };
        }
        public Dictionary<string, string> Names { get; set; }
        public Dictionary<string, bool> EnabledNames { get; set; }
    }
    
  2. 在你的xaml中,当你设置DataTemplate时,它的DataContext被设置为ItemsSource的单个条目。在您的例子中,这是KeyValuePair。你也可以使用MultiBinding绑定到你的EnabledNames字典,并使用转换器将你的Key转换为bool值从EnabledNames:

    <Window x:Class="Test31641637.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:Test31641637"
            Title="MainWindow" Height="350" Width="525"
            Name="mw">
        <Window.Resources>
            <ResourceDictionary>
                <local:MultiDictionaryConverter x:Key="multiDictionaryConverter" />
            </ResourceDictionary>
        </Window.Resources>
        <Window.DataContext>
            <local:ViewModel />
        </Window.DataContext>
        <ListBox x:Name="listBox" ItemsSource="{Binding Names}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <CheckBox >
                            <CheckBox.IsChecked>
                                <MultiBinding Converter="{StaticResource multiDictionaryConverter}" ConverterParameter="">
                                    <Binding Path="Key" Mode="OneWay"/>
                                    <Binding ElementName="mw" Path="DataContext.EnabledNames"/>
                                </MultiBinding>
                            </CheckBox.IsChecked>
                        </CheckBox>
                        <TextBlock Text="{Binding Path=Value}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Window>
    

和IMultiValueConverter:

public class MultiDictionaryConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (values.Length == 2 && values[0] is string && values[1] is Dictionary<string, bool>)
        {/*
            ((Dictionary<string, bool>)values[1])[values[0] as string] =
                !((Dictionary<string, bool>)values[1])[values[0] as string];*/
            return ((Dictionary<string, bool>)values[1])[values[0] as string];
        }
        return false;
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

我想这是最简单的方法来做到这一点(但它并不容易),它不会工作,因为当你点击复选框在你的ListBox, ConvertBack方法将被调用,但它是不可能转换回布尔值。因此,最简单的方法是创建一个特定的类来表示ListBox的单行:

public class Person
{
    public string ID { get; set; }
    public string Name { get; set; }
    public bool IsEnabled { get; set; }
}