我想将复选框列表绑定到WPF中的枚举值集合。 枚举不是[标志]。
上下文: 它用于过滤数据网格,其中每个项目都有我的枚举实例。 它不一定需要绑定到List,固定大小的集合也可以工作。
答案 0 :(得分:4)
假设您要绑定枚举的所有可能值,可以使用ObjectDataProvider进行绑定。
在您的资源(Window.Resources
或App.Resources
等)中声明此内容:
<ObjectDataProvider x:Key="enumValues" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:TestEnum"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
这基本上代表了对Enum.GetValues(typeof(TestEnum))
的调用,并将其作为数据源公开。
注意:您需要在sys
为local
之前声明命名空间sys
和clr-namespace:System;assembly=mscorlib
,local
是枚举的命名空间。
完成后,您可以将ObjectDataProvider用作绑定源,就像其他任何东西一样,例如:
<ListBox ItemsSource="{Binding Source={StaticResource enumValues}}"/>
执行此操作的非声明性方法只是在代码中分配:
someListBox.ItemsSource = Enum.GetValues(typeof(TestEnum));
对于绑定选定的项目,遗憾的是无法从Xaml设置SelectedItems属性,但您可以使用SelectionChanged事件:
<ListBox Name="lb" ItemsSource="{Binding Source={StaticResource enumValues}}" SelectionMode="Multiple" SelectionChanged="lb_SelectionChanged"></ListBox>
然后在事件中设置ViewModel(或您使用的任何内容)的属性:
private void lb_SelectionChanged(object sender, SelectionChangedEventArgs e) {
viewModel.SelectedValues = lb.SelectedItems.OfType<TestEnum>().ToList();
}
答案 1 :(得分:2)
这个适合你吗?它将任何Enum转换为Dictionary,这样您就可以访问Enum的内部int以及它们的名称(用于显示)。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sample
{
class Sample
{
public static IDictionary<String, Int32> ConvertEnumToDictionary<K>()
{
if (typeof(K).BaseType != typeof(Enum))
{
throw new InvalidCastException();
}
return Enum.GetValues(typeof(K)).Cast<Int32>().ToDictionary(currentItem => Enum.GetName(typeof(K), currentItem));
}
}
}
修改强>:
您可以使用ICollection类型的IDictionary属性Keys
和Values
来进行所需的绑定。
myListBox.ItemsSource = myEnumDictionary.Keys;
或者您当然可以直接在XAML中完成。
<ListBox ItemsSource="{Binding myEnumDictionary.Keys}"></ListBox>
答案 2 :(得分:1)
以下是如何在没有任何代码的情况下执行此操作,或者在视图中定义DataObjectProviders。
步骤1:创建一个可以存储ListBoxItem
值的新类,以及是否选中它的属性。
它需要实现INotifyPropetyChanged
以支持双向绑定是否被选中。我将它设为通用的,因此只需要定义一次,并且可以重用于任何类型。如果你已经有一个实现INotifyPropertyChanged的基类,你可以继承它并忽略这个类的前几行。
public class SelectableItem<T> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public SelectableItem(T val)
{
Value = val;
_isSelected = false;
}
public T Value { get; private set; }
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set
{
if (_isSelected == value) return;
_isSelected = value;
OnPropertyChanged();
}
}
}
步骤2:向ViewModel / DataContext添加SelectableItem
属性的集合。由于您的项目列表是可用枚举值的静态列表,因此无需将其实现为ObservableCollection或类似的任何内容。 ItemsSource只需要1次绑定。
public class ViewModel : ViewModelBase
{
public ViewModel()
{
AvailableItems = typeof(TestEnum).GetEnumValues().Cast<TestEnum>().Select((e) => new SelectableItem<TestEnum>(e)).ToList();
}
public IEnumerable<SelectableItem<TestEnum>> AvailableItems { get; private set; }
}
第3步:使用ItemContainerStyle
允许绑定IsSelected
的{{1}}属性:
ListBoxItem
要获取所选项,只需遍历AvailableItems属性并找到IsSelected = true的项。您甚至可以添加一个只读属性来为您执行此操作:
<ListBox ItemsSource="{Binding AvailableItems, Mode=OneTime}" SelectionMode="Extended">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Content" Value="{Binding Value}"/>
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
答案 3 :(得分:-1)
@ Dummy01所说的是正确的,但我认为大多数人都需要得到结果
Dictionary<int,string>
不是
Dictionary<string,int>
所以解决方案应该是
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sample
{
class Sample
{
public static IDictionary<String, Int32> ConvertEnumToDictionary<K>()
{
if (typeof(K).BaseType != typeof(Enum))
{
throw new InvalidCastException();
}
return Enum.GetValues(typeof(K)).Cast<Int32>().ToDictionary(i => i, i => Enum.GetName(typeof(K), i));
}
}
}
所以现在您将获得KeyValuePair<Int32,string>
如果您将枚举作为FLAGS使用,这将非常有用
[Flags]
public enum LogSystemLogType
{
All = 1 << 1,
CreateDatabase = 1 << 2,
CreateContract = 1 << 3,
}