我的 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 个地方。所以,我正在考虑使用枚举而不是使用静态文本。
在这种情况下,我有两个问题
Enum
属性绑定到下拉列表(例如 ComboBox
),这个规模如何?Enum
属性绑定到 ComboBox
我如何自定义标签以使其易于阅读,例如在视图中使用空格(例如:“one 1”)?下拉列表中的枚举是一个不错的选择,我一直都这样做。您将需要两个绑定和两个转换器 - 一个用于将枚举值转换为可以绑定到
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}}"
/>