gpt4 book ai didi

c# - 来自字符串的 IValueConverter

转载 作者:行者123 更新时间:2023-11-30 22:25:03 25 4
gpt4 key购买 nike

我有一个 Enum 需要显示在 ComboBox 中。我已经设法使用 ItemsSource 将枚举值获取到组合框,并且我正在尝试将它们本地化。我认为这可以使用值转换器来完成,但由于我的枚举值已经是字符串,编译器会抛出 IValueConverter 无法将字符串作为输入的错误。我不知道有任何其他方法可以将它们转换为其他字符串值。有没有其他方法可以做到这一点(不是本地化而是转换)?

我正在使用这个 marku 扩展来获取枚举值

[MarkupExtensionReturnType(typeof (IEnumerable))]
public class EnumValuesExtension : MarkupExtension {
public EnumValuesExtension() {}

public EnumValuesExtension(Type enumType) {
this.EnumType = enumType;
}

[ConstructorArgument("enumType")]
public Type EnumType { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) {
if (this.EnumType == null)
throw new ArgumentException("The enum type is not set");
return Enum.GetValues(this.EnumType);
}
}

在 Window.xaml 中

<Converters:UserTypesToStringConverter x:Key="userTypeToStringConverter" />
....
<ComboBox ItemsSource="{Helpers:EnumValuesExtension Data:UserTypes}"
Margin="2" Grid.Row="0" Grid.Column="1" SelectedIndex="0" TabIndex="1" IsTabStop="False">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type Data:UserTypes}">
<Label Content="{Binding Converter=userTypeToStringConverter}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

这里是转换器类,它只是一个测试类,还没有本地化。

public class UserTypesToStringConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
return (int) ((Data.UserTypes) value) == 0 ? "Fizička osoba" : "Pravna osoba";
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
return default(Data.UserTypes);
}
}

-- 编辑--

Enum 由 ADO.NET Diagram 生成,无法更改。

最佳答案

是的,当您将值传递给转换器时,它将成为 string 作为 GetStandardValues 的 Enum (EnumConverter) 的默认类型转换器(即 Enum.GetValues()) 以字符串形式返回可枚举的字段。

解决此问题的最佳方法是编写自定义类型转换器来装饰您的枚举。幸运的是,您不是第一个需要这样做的人,请参阅下面的代码示例。

public class EnumTypeConverter : EnumConverter
{
public EnumTypeConverter()
: base(typeof(Enum))
{
}

public EnumTypeConverter(Type type)
: base(type)
{
}

public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || TypeDescriptor.GetConverter(typeof(Enum)).CanConvertFrom(context, sourceType);
}

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string)
return GetEnumValue(EnumType, (string)value);

if (value is Enum)
return GetEnumDescription((Enum)value);

return base.ConvertFrom(context, culture, value);
}

public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (value is Enum && destinationType == typeof(string))
return GetEnumDescription((Enum)value);

if (value is string && destinationType == typeof(string))
return GetEnumDescription(EnumType, (string)value);

return base.ConvertTo(context, culture, value, destinationType);
}

public static bool GetIsEnumBrowsable(Enum value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var attributes = (BrowsableAttribute[])fieldInfo.GetCustomAttributes(typeof(BrowsableAttribute), false);

return !(attributes.Length > 0) || attributes[0].Browsable;
}

public static string GetEnumDescription(Enum value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

return (attributes.Length > 0) ? attributes[0].Description : value.ToString();
}

public static string GetEnumDescription(Type value, string name)
{
var fieldInfo = value.GetField(name);
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attributes.Length > 0) ? attributes[0].Description : name;
}

public static object GetEnumValue(Type value, string description)
{
var fields = value.GetFields();
foreach (var fieldInfo in fields)
{
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

if (attributes.Length > 0 && attributes[0].Description == description)
return fieldInfo.GetValue(fieldInfo.Name);

if (fieldInfo.Name == description)
return fieldInfo.GetValue(fieldInfo.Name);
}

return description;
}

public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}

public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
return base.GetStandardValues(context);
}

}

用法

[TypeConverter(typeof(EnumTypeConverter))]
public enum UserTypes : int
{
[Browsable(false)]
Unkown,
[Description("Local")]
LocalUser,
[Description("Network")]
NetworkUser,
[Description("Restricted")]
RestrictedUser
}

如您所见,上面的枚举我们使用了 Description 属性来用用户好友描述装饰每个字段,并覆盖了类型转换器以首先查找该属性。

不是 100% 但要让它与您的代码一起工作,您还需要将 MarkupExtension 更改为以下内容(注意:我没有测试过这个,所以您需要做一些工作是必须的)。

[MarkupExtensionReturnType(typeof (IEnumerable))]
public class EnumValuesExtension : MarkupExtension {

public EnumValuesExtension() {}

public EnumValuesExtension(Type enumType)
{
this.EnumType = enumType;
}

[ConstructorArgument("enumType")]
public Type EnumType { get; set; }

public override object ProvideValue(IServiceProvider serviceProvider)
{
if (this.EnumType == null)
throw new ArgumentException("The enum type is not set");

var converter = TypeDescriptor.GetConverter(this.EnumType);
if (converter != null && converter.GetStandardValuesSupported(this.EnumType))
return converter.GetStandardValues(this.EnumType);

return Enum.GetValues(this.EnumType);
}
}

此外,我只对应用程序进行了有限的本地化,但我相信这是最好且最易于维护的方法,因为它能够利用现有的 .NET 本地化工具(例如卫星程序集)

关于c# - 来自字符串的 IValueConverter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12479409/

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