gpt4 book ai didi

c# - 改进枚举到组合框的绑定(bind)(使用 MarkupExtension)

转载 作者:行者123 更新时间:2023-11-30 14:57:21 26 4
gpt4 key购买 nike

我试图最大限度地简化枚举到组合框的绑定(bind)。

在多个解决方案(ObjectDataProvider、Converter...)中,我选择了以下 MarkupExtension:

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" />

您会注意到我通过在 EnumMember 类中添加 ToString() 方法成功摆脱了 DisplayMemberPath="Display"

是否可以将 SelectedValuePath="Value" 属性替换为类运算符(在 EnumMember 内)或类似的东西?

谢谢!

最佳答案

有很多方法可以实现:

方法一

标记扩展的 ProvideValue 方法采用类型为 IServiceProvider 的参数,它提供 IProvideValueTarget 服务等。此接口(interface)公开属性 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();
}

方法二

如果您的应用程序中的所有组合框都将绑定(bind)到包装类 EnumMember,您可以在 Application.Resources 下的 ComboBox 的全局样式 下定义它,这样您就不会不必为每个组合框复制它。

即使您没有将 ComboBox 绑定(bind)到枚举值,也可以按实例覆盖 SelectedValuePath。

<Application.Resources>
<Style TargetType="ComboBox">
<Setter Property="SelectedValuePath" Value="Value"/>
</Style>
</Application.Resources>

方法三

您可以继承 ComboBox 和 OnItemsSourceChanged,将 SelectedValuePath 设置为 Value,以防 ItemsSource 是 EnumMember 类的数组

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);
}
}

XAML 中的用法:

<my:MyComboBox ItemsSource="{my:EnumSource {x:Type my:Options}}"
SelectedValue="{Binding Path=CurrentOption}"/>

附带说明,因为您创建了自己的标记扩展,所以您根本不需要 Binding。您可以像这样绑定(bind) ItemsSource:

    <ComboBox ItemsSource="{my:EnumSource {x:Type my:Options}}"
SelectedValue="{Binding CurrentOption}"/>

关于c# - 改进枚举到组合框的绑定(bind)(使用 MarkupExtension),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20911104/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com