如何将枚举绑定到下拉列表

问题描述 投票:0回答:1

我的 WPF 应用程序中有下拉菜单。它们是动态的,基于对同一屏幕或其他屏幕中其他控件的选择。 例如:

if (dropDown1.SelectedValue == "Name 1")
      dropDown2.ItemSource = new List<string>() { "one 1", "Two 2", "Three 3" };
else
      dropDown2.ItemSource = new List<string>() { "one 1", "Three 3" };

如上例所示,我在“if conditions”中使用了这些下拉菜单。如果下拉项目有任何变化,我必须在我使用的任何地方替换文本(在本例中为“名称 1”)。整个应用程序可能有 100 个地方。所以,我正在考虑使用枚举而不是使用静态文本。

在这种情况下,我有两个问题

  1. 是否可以通过数据绑定轻松地将
    Enum
    属性绑定到下拉列表(例如
    ComboBox
    ),这个规模如何?
  2. 如果我将
    Enum
    属性绑定到
    ComboBox
    我如何自定义标签以使其易于阅读,例如在视图中使用空格(例如:“one 1”)?
c# wpf mvvm enums dropdown
1个回答
0
投票

下拉列表中的枚举是一个不错的选择,我一直都这样做。您将需要两个绑定和两个转换器 - 一个用于将枚举值转换为可以绑定到

ItemsSource
的数组,另一个用于转换单个选定值。可以通过使用
DescriptionAttribute
属性来处理空格。这是代码:

这是

Enum
值的支持视图模型:

internal class EnumViewModel
{
    public EnumViewModel(Enum value)
    {
        this.Value = value;
        var backingField = value.GetType().GetField(value.ToString());
        var attr = backingField.GetCustomAttribute<DescriptionAttribute>();
        if (attr != null)
            this.Name = attr.Description;
        else
            this.Name = value.ToString();
    }

    public Enum Value
    {
        get;
    }

    public string Name
    {
        get;
    }

    // This is needed to ensure SelectedItem
    // works properly.
    public override bool Equals(object? obj)
    {
        if (obj is EnumViewModel evm)
            return Enum.Equals(this.Value, evm.Value);
        return false;
    }

    public override int GetHashCode()
    {
        return this.Value.GetHashCode();
    }

    public override string ToString()
    {
        return this.Name;
    }
}

两个 XAML 转换器:

// IMPORTANT - Use OneTime binding here, otherwise the choice array
// will be re-created every time the underlying bound value changes.
public class EnumToItemsSourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is Enum e))
            throw new Exception("EnumToItemsSourceConverter requires binding to an Enum value");
        var values = Enum.GetValues(e.GetType());
        return values.Cast<Enum>().Select(v => new EnumViewModel(v)).ToArray();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

public class EnumToSelectedItemConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is Enum e))
            throw new Exception("EnumToSelectedItemConverter requires binding to an Enum value");
        return new EnumViewModel(e);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is EnumViewModel evm))
            throw new Exception("EnumToSelectedItemConverter requires binding to an Enum value");
        return evm.Value;
    }
}

如果这看起来工作量很大,请考虑在示例中使用它是多么简单:

C#:

public enum TestEnum
{
    FirstChoice,
    SecondChoice,
    [Description("Custom Choice")]
    CustomChoice
}

public class TestViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    TestEnum _TestValue = TestEnum.FirstChoice;
    public TestEnum TestValue
    {
        get => _TestValue;
        set
        {
            _TestValue = value;
            PropertyChanged?.Invoke(
                this,
                new PropertyChangedEventArgs(nameof(TestValue)));
        }
    }
}

XAML:

    <ComboBox ItemsSource="{Binding TestValue, 
                    Mode=OneTime,
                    Converter={StaticResource EnumToItemsSourceConverter}}"
              SelectedItem="{Binding TestValue, 
                    Mode=TwoWay, 
                    Converter={StaticResource EnumToSelectedItemConverter}}"
              />

© www.soinside.com 2019 - 2024. All rights reserved.