如何在一个列表框中使用多个字典
本文关键字:字典 列表 一个 | 更新日期: 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。
你可以试试你的情况:
-
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; } }
-
在你的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; }
}