一、使用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