WPF 数据绑定:如何使用 XAML 将枚举数据绑定到组合框? [复制]
Posted
技术标签:
【中文标题】WPF 数据绑定:如何使用 XAML 将枚举数据绑定到组合框? [复制]【英文标题】:WPF Data binding: How to data bind an enum to combo box using XAML? [duplicate] 【发布时间】:2011-05-17 10:39:57 【问题描述】:我有一堂课:
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 文件:
<Window x:Class="Gui.Wpf.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test"
SizeToContent="WidthAndHeight">
<Grid>
<ComboBox
Name="ScopeComboBox"
Width="120"
Height="23"
Margin="12" />
</Grid>
</Window>
我想做两件事:
-
我希望将
DetailsScope
枚举值数据绑定到组合框值。我不想
直接绑定枚举值,因为最后一个枚举值将是 OtherDetail
而不是
Other detail
(添加了空格字符和小写字母“d”)。
我希望将组合框中的选定值数据绑定到在
AccountDetail
对象的实例。
你能帮帮我吗?谢谢。
更新:我发现这篇文章http://blogs.msdn.com/b/wpfsdk/archive/2007/02/22/displaying-enum-values-using-data-binding.aspx。我需要类似的东西。
【问题讨论】:
【参考方案1】:一个非常简单的方法是使用 ObjectDataProvider
<ObjectDataProvider MethodName="GetValues"
ObjectType="x:Type sys:Enum"
x:Key="DetailScopeDataProvider">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
使用 ObjectDataProvider 作为 ComboBox 的 ItemsSource,将 SelectedItem 绑定到 Scope 属性,并为每个 ComboBoxItem 的显示应用转换器
<ComboBox Name="ScopeComboBox"
ItemsSource="Binding Source=StaticResource DetailScopeDataProvider"
SelectedItem="Binding Scope"
Width="120"
Height="23"
Margin="12">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="Binding Converter=StaticResource CamelCaseConverter"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
在转换器中,您可以将 Regex 用于 this 问题中的 CamelCase 字符串拆分器。我使用了***的版本,但您可能可以使用更简单的版本。其他细节 + 正则表达式 = 其他细节。降低返回值,然后返回第一个字符大写的字符串应该会给你预期的结果
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, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$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;
【讨论】:
太棒了!谢谢,Meleak【参考方案2】:我一直这样做的方式如下。这个解决方案的美妙之处在于它是完全通用的,并且可以重复用于任何枚举类型。
1) 当你定义一个枚举时,使用一些自定义属性来提供一些信息。在此示例中,我使用 Browsable(false) 来指示此枚举器是内部的,并且我不想在组合框中看到此选项。 Description("") 允许我为枚举指定一个显示名称。
public enum MyEnumerationTypeEnum
[Browsable(false)]
Undefined,
[Description("Item 1")]
Item1,
[Description("Item 2")]
Item2,
Item3
2) 定义一个我称为 EnumerationManager 的类。这是一个分析枚举类型并生成值列表的泛型类。如果枚举器将 Browsable 设置为 false,它将被跳过。如果它具有描述属性,那么它将使用描述字符串作为显示名称。如果没有找到描述,它将只显示枚举器的默认字符串。
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 中添加一个部分
<ObjectDataProvider MethodName="GetValues" ObjectType="x:Type l:EnumerationManager" x:Key="OutputListForMyComboBox">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="l:MyEnumerationTypeEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
4) 现在只需将您的组合框的 ItemsSource 绑定到我们刚刚在资源字典中定义的这个键
<ComboBox Name="comboBox2"
ItemsSource="Binding Source=StaticResource OutputListForMyComboBox" />
如果您使用我上面的枚举尝试此代码,您应该会在组合框中看到 3 个项目:
Item 1
Item 2
Item3
希望这会有所帮助。
编辑: 如果您添加 LocalizableDescriptionAttribute 的实现并使用它来代替我使用的 Description 属性,那将是完美的。
【讨论】:
这是一个很好的方法。 将 SelectedItem 绑定回视图模型的最佳方法是什么?我试图直接绑定到视图模型中相同类型的枚举,但随后它将描述作为从控件发送的字符串并解析它(尤其是在本地化时)很痛苦? 终于找到解决办法了,谢谢。【参考方案3】:这是一个解决方案:创建一个包含所有可能性的属性(列表),然后将 ComboBox 绑定到该属性上。
在 XAML 中:
<ComboBox
Name="ScopeComboBox"
Width="120"
Height="23"
Margin="12"
ItemsSource="Binding Path=AccountDetailsProperty"
DisplayMemberPath="Value"/>
在后面的代码中:
public partial class Window1 : Window
public Window1()
AccountDetailsProperty = new List<AccountDetail>()
new AccountDetail(DetailScope.Business, "Business"),
new AccountDetail(DetailScope.OtherDetail, "Other details"),
new AccountDetail(DetailScope.Private, "Private"),
;
InitializeComponent();
this.DataContext = this;
public List<AccountDetail> AccountDetailsProperty get; set;
【讨论】:
尼古拉斯,感谢您的回复。我正在寻找一个更面向 XAML 的解决方案,例如:blogs.msdn.com/b/wpfsdk/archive/2007/02/22/…【参考方案4】:我会为此使用值转换器,这将允许您直接使用转换器进行绑定,您可以更改转换实现以使枚举的“更好”人类可读表示,即拆分大写字符。
有一篇关于这种方法的完整文章here。
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 );
【讨论】:
转换器是个好主意。怎么绑定? @Boris:上面链接的文章中都有详细说明以上是关于WPF 数据绑定:如何使用 XAML 将枚举数据绑定到组合框? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
WPF 让普通 CLR 属性支持 XAML 绑定(非依赖属性),这样 MarkupExtension 中定义的属性也能使用绑定了