一、使用ObjectDataProvider
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" SizeToContent="WidthAndHeight" Title="Show Enums in a ListBox using Binding"> <Window.Resources> <ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="AlignmentValues"> <ObjectDataProvider.MethodParameters> <x:Type TypeName="HorizontalAlignment" /> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </Window.Resources> <Border Margin="10" BorderBrush="Aqua" BorderThickness="3" Padding="8"> <StackPanel Width="300"> <TextBlock>Choose the HorizontalAlignment value of the Button:</TextBlock> <ListBox Name="myComboBox" SelectedIndex="0" Margin="8" ItemsSource="{Binding Source={StaticResource AlignmentValues}}"/> <Button Content="Click Me!" HorizontalAlignment="{Binding ElementName=myComboBox, Path=SelectedItem}"/> </StackPanel> </Border> </Window>
二、使用Converter
public class RadioButtonCheckedConverter: IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value.Equals(parameter); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value.Equals(true) ? parameter : Binding.DoNothing; } }
使用方法:
<RadioButton GroupName="EnumGroup" IsChecked="{Binding EnumProperty, Converter={StaticResource RadioButtonCheckedConverter}, ConverterParameter={x:Static src:TestEnum.Option1}}"> </RadioButton> <RadioButton GroupName="EnumGroup" IsChecked="{Binding EnumProperty, Converter={StaticResource RadioButtonCheckedConverter}, ConverterParameter={x:Static src:TestEnum.Option2}}"> </RadioButton> <RadioButton GroupName="EnumGroup" IsChecked="{Binding EnumProperty, Converter={StaticResource RadioButtonCheckedConverter}, ConverterParameter={x:Static src:TestEnum.Option3}}"> </RadioButton>
三、使用扩展的Markup
[MarkupExtensionReturnType(typeof(IEnumerable))] public class EnumValuesExtension : MarkupExtension { public EnumValuesExtension() { } public EnumValuesExtension(Type enumType) { this.EnumType = enumType; } [ConstructorArgument("enumType")] public Type EnumType { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { if (this.EnumType == null) throw new ArgumentException("The enum type is not set"); return Enum.GetValues(this.EnumType); } }
使用方法:
<ListBox Name="myComboBox" SelectedIndex="0" Margin="8" ItemsSource="{my:EnumValues HorizontalAlignment}"/>
四、使用资源文件实现Enum本地化
为Enum类型自定义Attribute
从而实现Enum与资源关联
/// <summary> /// Attribute for localization. /// </summary> [AttributeUsage(AttributeTargets.All,Inherited = false,AllowMultiple = true)] public sealed class LocalizableDescriptionAttribute : DescriptionAttribute { #region Public methods. // ------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the /// <see cref="LocalizableDescriptionAttribute"/> class. /// </summary> /// <param name="description">The description.</param> /// <param name="resourcesType">Type of the resources.</param> public LocalizableDescriptionAttribute (string description,Type resourcesType) : base(description) { _resourcesType = resourcesType; } #endregion #region Public properties. /// <summary> /// Get the string value from the resources. /// </summary> /// <value></value> /// <returns>The description stored in this attribute.</returns> public override string Description { get { if (!_isLocalized) { ResourceManager resMan = _resourcesType.InvokeMember( @"ResourceManager", BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, null, new object[] { }) as ResourceManager; CultureInfo culture = _resourcesType.InvokeMember( @"Culture", BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, null, new object[] { }) as CultureInfo; _isLocalized = true; if (resMan != null) { DescriptionValue = resMan.GetString(DescriptionValue, culture); } } return DescriptionValue; } } #endregion #region Private variables. private readonly Type _resourcesType; private bool _isLocalized; #endregion }
实现自定义的Converter
/// <summary> /// This class simply takes an enum and uses some reflection to obtain /// the friendly name for the enum. Where the friendlier name is /// obtained using the LocalizableDescriptionAttribute, which holds the localized /// value read from the resource file for the enum /// </summary> [ValueConversion(typeof(object), typeof(String))] public class EnumToFriendlyNameConverter : IValueConverter { #region IValueConverter implementation /// <summary> /// Convert value for binding from source object /// </summary> public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { // To get around the stupid WPF designer bug if (value != null) { FieldInfo fi = value.GetType().GetField(value.ToString()); // To get around the stupid WPF designer bug if (fi != null) { var attributes = (LocalizableDescriptionAttribute[]) fi.GetCustomAttributes(typeof (LocalizableDescriptionAttribute), false); return ((attributes.Length > 0) && (!String.IsNullOrEmpty(attributes[0].Description))) ? attributes[0].Description : value.ToString(); } } return string.Empty; } /// <summary> /// ConvertBack value from binding back to source object /// </summary> public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new Exception("Cant convert back"); } #endregion }
使用方法:
<ComboBox x:Name="cmbFoodType" ItemsSource="{Binding Source={StaticResource foodData}}" SelectedItem="{Binding Path=TestableClass.FoodType, Mode=TwoWay}" Height="Auto"> <ComboBox.ItemTemplate> <DataTemplate> <Label Content="{Binding Path=.,Mode=OneWay, Converter={StaticResource enumItemsConverter}}" Height="Auto" Margin="0" VerticalAlignment="Center"/> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
参考
Binding and Using Friendly Enums in WPF