WPF绑定枚举列表(或类似)列出复选框(WPF binding Enum list (or simi

2019-09-16 17:31发布

我想一个复选框列表绑定到枚举值在WPF的集合。 枚举不是[国旗]。

背景:这是用于过滤一个DataGrid,其中每个项目都有我的枚举的一个实例。 它不一定需要绑定到一个列表,一个固定大小的集合将正常工作。

Answer 1:

假设你要绑定到你的枚举所有可能的值,你可以用它做ObjectDataProvider的 。 在你的资源(声明这个Window.ResourcesApp.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))和公开它作为数据源。 注意:您需要声明的命名空间syslocal之前,其中sysclr-namespace:System;assembly=mscorliblocal是你的枚举的命名空间。

一旦你有,你可以使用ObjectDataProvider的有约束力的来源,就像别的,例如:

<ListBox ItemsSource="{Binding Source={StaticResource enumValues}}"/>

这样做的非声明的方式仅仅是分配在代码:

someListBox.ItemsSource = Enum.GetValues(typeof(TestEnum));

为了结合所选的项目,可惜selectedItems属性不能在XAML设置,但可以使用SelectionChanged事件:

<ListBox Name="lb" ItemsSource="{Binding Source={StaticResource enumValues}}" SelectionMode="Multiple" SelectionChanged="lb_SelectionChanged"></ListBox>

然后设置你的视图模型的财产(或任何你使用)事件:

private void lb_SelectionChanged(object sender, SelectionChangedEventArgs e) {
    viewModel.SelectedValues = lb.SelectedItems.OfType<TestEnum>().ToList();
}


Answer 2:

这是否一个适合你? 任何枚举转换成词典,让你可以访问你的枚举的内部整数,也给他们的名字(用于显示)。

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));
        }
    }
}

编辑

您可以使用IDictionary的属性KeysValues它们类型的ICollection做你想要的绑定。

myListBox.ItemsSource = myEnumDictionary.Keys;

或者当然你也可以在XAML直接做到这一点。

<ListBox ItemsSource="{Binding myEnumDictionary.Keys}"></ListBox>


Answer 3:

下面是如何做到这一点无需任何代码后面,或者在您的视图定义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步:添加的集合SelectableItem属性为您的视图模型/ DataContext的。 由于您的项目名单可枚举值的静态列表,没有必要实现它作为一个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的你的财产ListBoxItem S:

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

为了获得所选择的项目,只需通过AvailableItems财产迭代,并发现已IsSelected =真正的项目。 您甚至可以添加一个只读属性,为你这样做:

public IEnumerable<TestEnum> SelectedItems
{
  get => AvailableItems.Where((o) => o.IsSelected).Select((o) => o.Value).ToList();
}


文章来源: WPF binding Enum list (or similar) to list of checkboxes