C# 改进枚举到组合框绑定(使用MarkupExtension)
我试图最大限度地简化枚举到组合框的绑定 在多个解决方案(ObjectDataProvider、Converter…)中,我选择了以下MarkupExtension:C# 改进枚举到组合框绑定(使用MarkupExtension),c#,wpf,binding,member,C#,Wpf,Binding,Member,我试图最大限度地简化枚举到组合框的绑定 在多个解决方案(ObjectDataProvider、Converter…)中,我选择了以下MarkupExtension: public class EnumSource : MarkupExtension { public class EnumMember { public string Display { get; set; } public object Value { get; set; }
public class EnumSource : MarkupExtension
{
public class EnumMember
{
public string Display { get; set; }
public object Value { get; set; }
public override string ToString()
{
return Display;
}
}
private readonly Type EnumType;
public EnumSource(Type type)
{
EnumType = type;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
var enumValues = Enum.GetValues(EnumType);
return (
from object enumValue in enumValues
select new EnumMember
{
Value = enumValue,
Display = GetDescription(enumValue)
}).ToArray();
}
private string GetDescription(object enumValue)
{
var descriptionAttribute = EnumType
.GetField(enumValue.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.FirstOrDefault() as DescriptionAttribute;
return (descriptionAttribute != null) ? descriptionAttribute.Description : enumValue.ToString();
}
}
<ComboBox ItemsSource="{Binding Source={my:EnumSource {x:Type my:Options}}}" SelectedValue="{Binding Path=CurrentOption}" SelectedValuePath="Value" />
公共类枚举源:MarkupExtension
{
公共类枚举成员
{
公共字符串显示{get;set;}
公共对象值{get;set;}
公共重写字符串ToString()
{
返回显示;
}
}
私有只读类型EnumType;
公共枚举源(类型)
{
枚举类型=类型;
}
公共覆盖对象ProviderValue(IServiceProvider服务提供程序)
{
var enumValues=Enum.GetValues(EnumType);
返回(
从枚举值中的对象枚举值
选择新成员
{
值=枚举值,
Display=GetDescription(枚举值)
}).ToArray();
}
私有字符串GetDescription(对象枚举值)
{
变量descriptionAttribute=EnumType
.GetField(enumValue.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute),false)
.FirstOrDefault()作为描述属性;
return(descriptionAttribute!=null)?descriptionAttribute.Description:enumValue.ToString();
}
}
您可以注意到,我通过在EnumMember类中添加一个ToString()方法,成功地摆脱了DisplayMemberPath=“Display”
是否可以将SelectedValuePath=“Value”属性替换为类运算符(位于EnumMember内部)或类似的内容
谢谢 这是不可能的,因为SelectedValue根据SelectedValuePath中提到的属性从SelectedItem中提取特定属性的值。这意味着SelectedValue和SelectedValuePath一起工作。但是,如果您想在不提及SlectedValuePath的情况下执行此操作,请使用SelectedItem属性进行绑定 更新这是ViewModel中的一个属性 xaml
实现这一目标的方法有很多: 方法1 标记扩展的
ProvideValue
方法采用类型为IServiceProvider
的参数,该参数提供IProvideValueTarget
服务。此接口公开属性TargetObject
,该属性允许检索目标对象(本例中为组合框)
您可以这样设置SelectedValuePath
:
public override object ProvideValue(IServiceProvider serviceProvider)
{
IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (target != null && target.TargetObject is ComboBox)
{
((ComboBox)target.TargetObject).SelectedValuePath = "Value";
}
var enumValues = Enum.GetValues(EnumType);
return (
from object enumValue in enumValues
select new EnumMember
{
Value = enumValue,
Display = GetDescription(enumValue)
}).ToArray();
}
<ComboBox ItemsSource="{my:EnumSource {x:Type my:Options}}"
SelectedValue="{Binding CurrentOption}"/>
方法2 如果应用程序中的所有组合框都将绑定到包装类
EnumMember
,您可以在Application.Resources下的组合框的全局样式下定义它,这样您就不必为每个组合框复制它
即使在这种情况下,您并没有将ComboBox绑定到枚举值,SelectedValuePath也可以覆盖每个实例
<Application.Resources>
<Style TargetType="ComboBox">
<Setter Property="SelectedValuePath" Value="Value"/>
</Style>
</Application.Resources>
XAML中的用法:
<my:MyComboBox ItemsSource="{my:EnumSource {x:Type my:Options}}"
SelectedValue="{Binding Path=CurrentOption}"/>
谢谢你的解释,虽然我没有设法让它与SelectedItem绑定一起工作。如何指定确切的路径?我更新了答案。请参阅更新我尝试了它并为我工作。只需在ViewModel中选择EdItem.value即可获得该值。
public class MyComboBox : ComboBox
{
protected override void OnItemsSourceChanged(IEnumerable oldValue,
IEnumerable newValue)
{
if (newValue != null &&
newValue.GetType().Equals(typeof(EnumSource.EnumMember[])))
{
SelectedValuePath = "Value";
}
base.OnItemsSourceChanged(oldValue, newValue);
}
}
<my:MyComboBox ItemsSource="{my:EnumSource {x:Type my:Options}}"
SelectedValue="{Binding Path=CurrentOption}"/>
<ComboBox ItemsSource="{my:EnumSource {x:Type my:Options}}"
SelectedValue="{Binding CurrentOption}"/>