如果希望能够简单地从xaml绑定枚举,可以编写标记扩展类。前段时间我写了一篇关于它的博文:
http://simonkatanski.blogspot.com/2013/02/enum-combobox-using-markupextension.html
代码如下:
public class EnumValuesExtension : MarkupExtension
{
private Type _enumType;
private String _resourceName;
private bool _addEmptyValue = false;
// Enumeration type
public Type EnumType
{
set { _enumType = value; }
}
// Name of the class of the .resx file
public String ResourceName
{
set { _resourceName = value; }
}
// Add empty value flag
public Boolean AddEmptyValue
{
set { _addEmptyValue = value; }
}
public EnumValuesExtension()
{
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
// Enumeration type not passed through XAML
if (_enumType == null)
throw new ArgumentNullException("EnumType (Property not set)");
if (!_enumType.IsEnum)
throw new ArgumentNullException("Property EnumType must be an enum");
// Bindable properties list
List<dynamic> list = new List<dynamic>();
if (!String.IsNullOrEmpty(_resourceName))
{
// Name of the resource class
Type type = Type.GetType(_resourceName);
if (type == null)
throw new ArgumentException(
"Resource name should be a fully qualified name");
// We iterate through the Enum values
foreach (var enumName in Enum.GetNames(_enumType))
{
string translation = string.Empty;
var property = type.GetProperty(enumName,
BindingFlags.Static |
BindingFlags.Public |
BindingFlags.NonPublic);
// If there's not translation for specific Enum value,
// there'll be a message shown instead
if (property == null)
translation = String.Format(
"Field {0} not found in the resource file {1}",
enumName,
_resourceName);
else
translation = property.GetValue(null, null).ToString();
list.Add(GetNamed(translation, enumName));
}
// Adding empty row
if (_addEmptyValue)
list.Add(GetEmpty());
return list;
}
// If there's no resource provided Enum values will be used
// without translation
foreach (var enumName in Enum.GetNames(_enumType))
list.Add(GetNamed(enumName, enumName));
if (_addEmptyValue)
list.Add(GetEmpty());
return list;
}
// Create one item which will fill our ComboBox ItemSource list
private dynamic GetNamed(string translation, string enumName)
{
// We create a bindable context
dynamic bindableResult = new ExpandoObject();
// This dynamically created property will be
// bindable from XAML (through DisplayMemberPath or wherever)
bindableResult.Translation = translation;
// We're setting the value, which will be passed to SelectedItem
// of the ComboBox
bindableResult.Enum = enumName;
return bindableResult;
}
// Create one empty item which will fill our ComboBox ItemSource list
private dynamic GetEmpty()
{
dynamic bindableResult = new ExpandoObject();
bindableResult.Translation = String.Empty;
bindableResult.Enum = null;
return bindableResult;
}
}
您可以在代码中使用此类,如下所示:
<StackPanel>
<ComboBox Height="100" Width="200"
SelectedValuePath="Enum"
DisplayMemberPath="Translation"
ItemsSource="{Binding Source={local:EnumValues EnumType=local:TestEnum}}"
Margin="98,0,76,0"
SelectedValue="{Binding SelectedItemInYourViewModel}"/>
</StackPanel>
然后,您只需将枚举作为上述xaml中的枚举类型传递。这样就可以使用xaml中的枚举。
我粘贴在这里的版本和博客中的版本有额外的代码,用于组合中的热交换值及其翻译的等效值(如果您正在处理多语言应用程序),您应该能够轻松删除该代码。