C# WPF数据绑定:如何使用XAML将枚举数据绑定到组合框?
我有一门课:C# WPF数据绑定:如何使用XAML将枚举数据绑定到组合框?,c#,wpf,xaml,data-binding,combobox,C#,Wpf,Xaml,Data Binding,Combobox,我有一门课: public class AccountDetail { public DetailScope Scope { get { return scope; } set { scope = value; } } public string Value { get { return this.value; } set { this.value = value; } }
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
enum值数据绑定到组合框值。我不想
直接绑定枚举值,因为最后一个枚举值将是OtherDetail
,而不是
其他详细信息
(添加了空格字符和小写字母“d”)李>
AccountDetail
对象的实例李>
你能帮我吗?谢谢
更新:我找到了这个帖子。我需要类似的东西 这里有一个解决方案:创建一个包含所有可能性的属性(列表),然后将组合框绑定到该属性上 在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; }
}
公共部分类窗口1:窗口
{
公共窗口1()
{
AccountDetailsProperty=新列表()
{
新账户详情(DetailScope.Business,“业务”),
新账户详情(DetailScope.OtherDetail,“其他详情”),
新AccountDetail(DetailScope.Private,“Private”),
};
初始化组件();
this.DataContext=this;
}
公共列表AccountDetailsProperty{get;set;}
}
我通常的做法如下。此解决方案的优点在于它是完全通用的,并且可以重新用于任何枚举类型
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>
希望这有帮助
编辑:
如果您添加LocalizableDescriptionAttribute的实现并使用它,而不是我使用的Description属性,那将是完美的。我将为此使用值转换器,这将允许您使用转换器直接绑定,您可以更改转换实现以实现“更好”枚举的可读表示,即按大写字符拆分 有一篇关于这种方法的完整文章
一种非常简单的方法是使用ObjectDataProvider
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="DetailScopeDataProvider">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
尼古拉斯,谢谢你的回复。我正在寻找一个更面向XAML的解决方案,比如:converter是一个好主意。我该怎么装订?@Boris:上面链接的文章中都有详细说明,太棒了!谢谢,Meleak这是一个很好的方法。将SelectedItem绑定回viewmodel的最佳方法是什么?我试图直接绑定到viewmodel中相同类型的枚举,但是它会以字符串的形式从控件中获取描述,并且解析它(特别是在本地化的情况下)很痛苦?
Item 1
Item 2
Item3
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 );
}
}
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="DetailScopeDataProvider">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<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>
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;
}
}