WPF数据绑定:如何使用XAML将枚举数据绑定到combobox?
我上课了:
public class AccountDetail { public DetailScope Scope { get { return scope; } set { scope = value; } } public string Value { get { return this.value; } set { this.value = value; } } private DetailScope scope; private string value; public AccountDetail(DetailScope scope, string value) { this.scope = scope; this.value = value; } }
和一个枚举:
public enum DetailScope { Private, Business, OtherDetail }
最后,我有一个.xaml文件:
我想做两件事:
- 我希望数据将
DetailsScope
枚举值绑定到combobox值。 我不希望直接绑定枚举值,因为最后一个枚举值是OtherDetail
而不是Other detail
(添加了空格字符和小写字母’d’)。 - 我希望将combobox中的选定值绑定到
AccountDetail
对象实例中指定的值。
你能救我吗? 谢谢。
更新:我发现这篇文章http://blogs.msdn.com/b/wpfsdk/archive/2007/02/22/displaying-enum-values-using-data-binding.aspx 。 我需要类似的东西。
一个非常简单的方法是使用ObjectDataProvider
使用ObjectDataProvider作为ComboBox的ItemsSource,将SelectedItem绑定到Scope属性并应用转换器来显示每个ComboBoxItem
在转换器中,您可以在此问题中使用Regex for CamelCase字符串拆分器。 我使用的是最先进的版本,但您可以使用更简单的版本。 OtherDetail +正则表达式=其他细节。 使返回值更低,然后返回带有第一个字符UpperCase的字符串应该给出预期的结果
public class CamelCaseConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string enumString = value.ToString(); string camelCaseString = Regex.Replace(enumString, "([az](?=[AZ])|[AZ](?=[AZ][az]))", "$1 ").ToLower(); return char.ToUpper(camelCaseString[0]) + camelCaseString.Substring(1); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value; } }
我一直这样做的方式如下。 这个解决方案的优点在于它完全通用,可以重复用于任何枚举类型。
1)定义枚举时,请使用一些自定义属性来提供一些信息。 在这个例子中,我使用了Browsable(false)来表示这个枚举器是内部的,我不想在combobox中看到这个选项。 描述(“”)允许我指定枚举的显示名称。
public enum MyEnumerationTypeEnum { [Browsable(false)] Undefined, [Description("Item 1")] Item1, [Description("Item 2")] Item2, Item3 }
2)定义一个我称之为EnumerationManager的类。 这是一个分析Enumeration类型并生成值列表的generics类。 如果枚举器将Browsable设置为false,则将跳过它。 如果它具有Description属性,那么它将使用描述字符串作为显示名称。 如果没有找到描述,它将只显示枚举器的默认字符串。
public class EnumerationManager { public static Array GetValues(Type enumeration) { Array wArray = Enum.GetValues(enumeration); ArrayList wFinalArray = new ArrayList(); foreach(Enum wValue in wArray) { FieldInfo fi = enumeration.GetField(wValue.ToString()); if(null != fi) { BrowsableAttribute[] wBrowsableAttributes = fi.GetCustomAttributes(typeof(BrowsableAttribute),true) as BrowsableAttribute[]; if(wBrowsableAttributes.Length > 0) { // If the Browsable attribute is false if(wBrowsableAttributes[0].Browsable == false) { // Do not add the enumeration to the list. continue; } } DescriptionAttribute[] wDescriptions = fi.GetCustomAttributes(typeof(DescriptionAttribute),true) as DescriptionAttribute[]; if(wDescriptions.Length > 0) { wFinalArray.Add(wDescriptions[0].Description); } else wFinalArray.Add(wValue); } } return wFinalArray.ToArray(); } }
3)在您的xaml中添加ResourceDictionary中的一个部分
4)现在只需将combobox的ItemsSource绑定到我们刚刚在资源字典中定义的这个键
如果您使用上面的枚举尝试此代码,您应该在combobox中看到3个项目:
Item 1 Item 2 Item3
希望这可以帮助。
编辑:如果您添加LocalizableDescriptionAttribute的实现,并使用它而不是我正在使用的Description属性将是完美的。
这是一个解决方案:您创建一个包含所有可能性的属性(列表),并在该属性上绑定您的ComboBox。
在XAML中:
并在代码背后:
public partial class Window1 : Window { public Window1() { AccountDetailsProperty = new List() { new AccountDetail(DetailScope.Business, "Business"), new AccountDetail(DetailScope.OtherDetail, "Other details"), new AccountDetail(DetailScope.Private, "Private"), }; InitializeComponent(); this.DataContext = this; } public List AccountDetailsProperty { get; set; } }
我会使用一个值转换器,这将允许您使用转换器直接绑定,您可以更改转换实现,以便为枚举的“更好”的人类可读表示,即拆分大写字符。
这里有一篇关于这种方法的完整文章。
public class MyEnumToStringConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value.ToString(); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return (MyEnum) Enum.Parse( typeof ( MyEnum ), value.ToString(), true ); } }