C# 将TypeConverter直接绑定到枚举
我有以下场景:我有一个枚举,希望绑定它并在DataGridViewTextBoxColumn上的DataGridView(databound)中显示它 这是我的枚举:C# 将TypeConverter直接绑定到枚举,c#,.net,datagridview,enums,typeconverter,C#,.net,Datagridview,Enums,Typeconverter,我有以下场景:我有一个枚举,希望绑定它并在DataGridViewTextBoxColumn上的DataGridView(databound)中显示它 这是我的枚举: //[TypeConverter(typeof(EnumStringConverter))] public enum YesNoNA { [EnumDescription("Yes")] Yes, [EnumDescription("No")] No, [En
//[TypeConverter(typeof(EnumStringConverter))]
public enum YesNoNA
{
[EnumDescription("Yes")]
Yes,
[EnumDescription("No")]
No,
[EnumDescription("N/A")]
NA
}
下面是一个使用它的简单属性:
[TypeConverter(typeof(EnumStringConverter))]
public YesNoNA HighLimitWithinBounds { get; protected set; }
在上述情况下,typeconverter工作正常。它为我做了转换
然而,这比我的理想解决方案更复杂。如果我将typeconverter放在枚举本身上(取消对上面代码的注释),并注释掉属性上的typeconverter,那么typeconverter将不再被调用
我在其他课程上也做过这个约定,效果很好
为什么将typeconverter直接放在枚举上不起作用
以下是我的typeconverter供参考:
public class EnumStringConverter : TypeConverter
{
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, Object value, Type destinationType)
{
if (value != null && destinationType == typeof(string))
{
return "Edited to protect the innocent!";
}
return TypeDescriptor.GetConverter(typeof(Enum)).ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
{
return true;
}
return base.CanConvertTo(context, destinationType);
}
};
我不知道你所说的“这比我的理想解决方案更复杂”是什么意思。我有一种不同于你的方法,但它可能不那么复杂。我想说,我的方法涉及到更多的前期开销,但在应用程序中使用它的次数越多,就会得到回报。它使您的应用程序可以本地化,这意味着您不必向每个枚举值添加属性 1)创建资源管理器缓存 这部分是可选的;但是,如果您像我一样多次使用多个资源文件,则可以通过减少反射来提高性能
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Resources;
namespace AppResourceLib.Public.Reflection
{
internal static class ResourceManagerCache
{
private static Dictionary<Type, ResourceManager> _resourceManagerMap =
new Dictionary<Type, ResourceManager>();
public static ResourceManager GetResourceManager(Type resourceType)
{
ResourceManager resourceManager = null;
// Make sure the type is valid.
if (null != resourceType)
{
// Try getting the cached resource manager.
if (!ResourceManagerCache._resourceManagerMap.TryGetValue(resourceType, out resourceManager))
{
// If it is not in the cache create it.
resourceManager = resourceType.InvokeMember(
"ResourceManager",
(BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic),
null,
null,
null) as ResourceManager;
// If it was created, add the resource manager to the cache.
if (null != resourceManager)
{
ResourceManagerCache._resourceManagerMap.Add(resourceType, resourceManager);
}
}
}
return resourceManager;
}
}
}
4)创建资源(.resx)字符串文件
现在,您需要创建一个资源文件,该文件将包含您想要的枚举键值样式的描述。我的意思是,在字符串资源的“名称”列中,您将输入各个枚举的确切名称,在“值”列中,您将输入转换该枚举时要获取的字符串。例如,假设您有以下枚举
public enum MyColors
{
Black,
Blue,
White
}
那么您的字符串资源文件将如下所示
名称|值
黑色|一种深色蓝色|冷色
白色|明亮的颜色 5)使用属性创建枚举 现在,我们最终使用LocalizedDescription进行Enum声明。传递到LocalizedDescription属性的参数是字符串资源文件的类型。现在使用转换器时,它将看到枚举类型的属性,获取资源文件,查找与特定枚举值的字符串值匹配的键字符串,并将资源文件中的值作为转换后的字符串返回
using AppResourceLib.Public;
using AppResourceLib.Public.Reflection;
namespace MyEnums
{
[LocalizedDescription(typeof(MyColorStrings))]
public enum MyColors
{
Black,
Blue,
White
}
}
这种方法的主要缺点是,只有当资源文件中的“Name”键与枚举值的名称匹配时,它才会起作用。这是在资源文件中引用字符串值而不为每个枚举指定描述属性的唯一方法。那么如何使用它来显示值呢?这里有一个例子
在xaml代码中,您需要创建一个数据提供程序,以将枚举值获取到UI元素(我在这里使用了一个组合框…)。然后,您将希望使转换器可用,并模板化您的UI元素以使用枚举转换器。就这样
<!-- Enum Colors -->
<ObjectDataProvider x:Key="MyColorEnums"
MethodName="GetValues"
ObjectType="{x:Type sys:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="MyColors"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<!-- Enum Type Converter -->
<LocalizedDescriptionConverter x:Key="EnumConverter"/>
<!-- Dropdown Expand ComboBox Template -->
<DataTemplate x:Key="MyColorsComboBoxTemplate">
<Label Content="{Binding Path=., Mode=OneWay,
Converter={StaticResource EnumConverter}}"
Height="Auto" Margin="0" VerticalAlignment="Center"/>
</DataTemplate>
<!-- And finally the ComboBox that will display all of your enum values
but will use the strings from the resource file instead of enum.ToString() -->
<ComboBox Width="80" HorizontalAlignment="Left"
ItemTemplate="{StaticResource MyColorsComboBoxTemplate}"
ItemsSource="{Binding Source={StaticResource MyColorEnums}}">
哇,对不起,时间太长了。我不确定这对你来说是否太复杂,但这是另一种选择。希望有帮助 可能重复的诽谤无关。上面已经实现了该线程中答案的解决方案。这个问题更进一步。我的示例与您的示例非常相似(您在使用资源文件方面更进一步,我在其他地方也使用资源文件来获得多语言支持)。我提到的复杂性差异在于,我的示例需要在属性上而不是在枚举本身上使用typeconverter。不幸的是,我不认为我们的例子会匹配。您使用的是xaml,我使用的是纯.net winforms。您正在使用您的组合框。您的xaml专门将combobox绑定到您需要的转换器,这正是我试图避免的(我认为我不会成功)。谢谢你的回复!哦,我明白你的意思了。对不起,我帮不上忙。
using AppResourceLib.Public;
using AppResourceLib.Public.Reflection;
namespace MyEnums
{
[LocalizedDescription(typeof(MyColorStrings))]
public enum MyColors
{
Black,
Blue,
White
}
}
<!-- Enum Colors -->
<ObjectDataProvider x:Key="MyColorEnums"
MethodName="GetValues"
ObjectType="{x:Type sys:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="MyColors"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<!-- Enum Type Converter -->
<LocalizedDescriptionConverter x:Key="EnumConverter"/>
<!-- Dropdown Expand ComboBox Template -->
<DataTemplate x:Key="MyColorsComboBoxTemplate">
<Label Content="{Binding Path=., Mode=OneWay,
Converter={StaticResource EnumConverter}}"
Height="Auto" Margin="0" VerticalAlignment="Center"/>
</DataTemplate>
<!-- And finally the ComboBox that will display all of your enum values
but will use the strings from the resource file instead of enum.ToString() -->
<ComboBox Width="80" HorizontalAlignment="Left"
ItemTemplate="{StaticResource MyColorsComboBoxTemplate}"
ItemsSource="{Binding Source={StaticResource MyColorEnums}}">