将枚举属性数据绑定到WPF中的ComboBox
时间:2020-03-05 18:52:08 来源:igfitidea点击:
以下面的代码为例:
public enum ExampleEnum { FooBar, BarFoo } public class ExampleClass : INotifyPropertyChanged { private ExampleEnum example; public ExampleEnum ExampleProperty { get { return example; } { /* set and notify */; } } }
我想要将属性ExampleProperty数据绑定到ComboBox,以便它显示选项" FooBar"和" BarFoo",并在TwoWay模式下工作。理想情况下,我希望我的ComboBox定义看起来像这样:
<ComboBox ItemsSource="What goes here?" SelectedItem="{Binding Path=ExampleProperty}" />
目前,我在我手动执行绑定的Window中安装了ComboBox.SelectionChanged和ExampleClass.PropertyChanged事件的处理程序。
有更好的或者某种规范的方法吗?我们通常会使用转换器吗,如何用正确的值填充ComboBox?我什至不想现在就开始使用i18n。
编辑
因此回答了一个问题:如何用正确的值填充ComboBox。
通过ObjectDataProvider从静态Enum.GetValues方法检索Enum值作为字符串列表:
<Window.Resources> <ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="ExampleEnumValues"> <ObjectDataProvider.MethodParameters> <x:Type TypeName="ExampleEnum" /> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </Window.Resources>
我可以将其用作我的ComboBox的ItemsSource:
<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}"/>
解决方案
回答
我不知道是否有可能仅在XAML中使用,但是请尝试以下操作:
为ComboBox命名,以便我们可以在后面的代码中访问它:" typesComboBox1"
现在尝试以下
typesComboBox1.ItemsSource = Enum.GetValues(typeof(ExampleEnum));
回答
尝试使用
<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}" SelectedValue="{Binding Path=ExampleProperty}" />
回答
我们可以考虑这样的事情:
- 定义文本块或者要用于显示枚举的任何其他控件的样式:
<Style x:Key="enumStyle" TargetType="{x:Type TextBlock}"> <Setter Property="Text" Value="<NULL>"/> <Style.Triggers> <Trigger Property="Tag"> <Trigger.Value> <proj:YourEnum>Value1<proj:YourEnum> </Trigger.Value> <Setter Property="Text" Value="{DynamicResource yourFriendlyValue1}"/> </Trigger> <!-- add more triggers here to reflect your enum --> </Style.Triggers> </Style>
- 为ComboBoxItem定义样式
<Style TargetType="{x:Type ComboBoxItem}"> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate> <TextBlock Tag="{Binding}" Style="{StaticResource enumStyle}"/> </DataTemplate> </Setter.Value> </Setter> </Style>
- 添加一个组合框并使用枚举值加载它:
<ComboBox SelectedValue="{Binding Path=your property goes here}" SelectedValuePath="Content"> <ComboBox.Items> <ComboBoxItem> <proj:YourEnum>Value1</proj:YourEnum> </ComboBoxItem> </ComboBox.Items> </ComboBox>
如果枚举很大,那么我们当然可以在代码中执行相同的操作,从而省去了很多键入操作。
我喜欢这种方法,因为它使本地化变得容易,我们一次定义所有模板,然后只更新字符串资源文件。
回答
我们可以创建自定义标记扩展。
用法示例:
enum Status { [Description("Available.")] Available, [Description("Not here right now.")] Away, [Description("I don't have time right now.")] Busy }
<ComboBox ItemsSource="{Binding Source={my:Enumeration {x:Type my:Status}}}" DisplayMemberPath="Description" SelectedValue="{Binding CurrentStatus}" SelectedValuePath="Value" />
以及实施...
public class EnumerationExtension : MarkupExtension { private Type _enumType; public EnumerationExtension(Type enumType) { if (enumType == null) throw new ArgumentNullException("enumType"); EnumType = enumType; } public Type EnumType { get { return _enumType; } private set { if (_enumType == value) return; var enumType = Nullable.GetUnderlyingType(value) ?? value; if (enumType.IsEnum == false) throw new ArgumentException("Type must be an Enum."); _enumType = value; } } public override object ProvideValue(IServiceProvider serviceProvider) { var enumValues = Enum.GetValues(EnumType); return ( from object enumValue in enumValues select new EnumerationMember{ Value = enumValue, Description = GetDescription(enumValue) }).ToArray(); } private string GetDescription(object enumValue) { var descriptionAttribute = EnumType .GetField(enumValue.ToString()) .GetCustomAttributes(typeof (DescriptionAttribute), false) .FirstOrDefault() as DescriptionAttribute; return descriptionAttribute != null ? descriptionAttribute.Description : enumValue.ToString(); } public class EnumerationMember { public string Description { get; set; } public object Value { get; set; } } }