【问题标题】:TypeConverter not working with ExpandoObject and DataGridTypeConverter 不适用于 ExpandoObject 和 DataGrid
【发布时间】:2017-06-07 14:26:58
【问题描述】:

我有一个 Poco 类,其中一个属性是枚举类型。
为了使枚举属性在 UI 层 (WPF) 上可本地化,我为查找本地化枚举值的枚举类型创建了一个 TypeConverter。 此 POCO 类的实例列表绑定到 WPF DataGrid:

// in the ViewModel:
public Pocos = CollectionViewSource.GetDefaultView( DataLayer.GetPocos() );

效果很好。

后来我重构了代码,使数据层不再返回List<Poco>,而是返回List<ExpandoObject>

public Pocos = CollectionViewSource.GetDefaultView( DataLayer.GetExpandos() );

这些ExpandoObjects 是数据库查询的结果,仅包含原始Poco's 属性的子集,具体取决于选择语句。

一切正常,除了不再调用的枚举属性的TypeConverter

TypeConverter 仍然是暴露的,所以这有效:

dynamic eo = new ExpandoObject();
eo.EnumProperty = MyEnum.SomeValue;
var converter = TypeConverter.GetConverter( (eo.EnumProperty).GetType() );
var result = converter.ConvertTo( eo.EnumProperty, typeof( string ) );

我不知道 WPF 的 DataGrid 内部发生了什么。我的印象是,无论出于何种原因,它只是在枚举类型属性上调用ToString(),而不是调用TypeConverter

有什么方法可以让它工作吗?

实现细节:

XAML:

<DataGrid x:Name="PocoGrid" x:FieldModifier="public"  
  Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2"
  ItemsSource="{Binding Pocos}" 
  SelectedItem="{Binding SelectedPoco}"
  bh:DataGridColumnsBehavior.BindableColumns="{Binding PocoColumns}"
  IsSynchronizedWithCurrentItem="True" IsReadOnly="True" AutoGenerateColumns="False">
  <DataGrid.InputBindings>
    <MouseBinding MouseAction="LeftDoubleClick" Command="{Binding PocoDoubleClick}" CommandParameter="{Binding Pocos/}"/>
  </DataGrid.InputBindings>
</DataGrid>

类型转换器:

public abstract class EnumTypeConverterBase : TypeConverter
{
   public static ILocalizedResourceProvider ResourceProvider { get; set; } = null;
}

public class EnumTypeConverter<T> : EnumTypeConverterBase where T : struct, IConvertible, IComparable
{
   private static string typeParameterName = typeof(T).Name;

   public override bool CanConvertFrom( ITypeDescriptorContext context, Type sourceType )
   {
      if( sourceType == typeof( string ) )
         return true;
      return base.CanConvertFrom( context, sourceType );
   }

   public override object ConvertFrom( ITypeDescriptorContext context, CultureInfo culture, object value )
   {
      throw new NotImplementedException();
   }

   public override object ConvertTo( ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType )
   {
      string val = value.ToString();

      if( ResourceProvider == null )
         return val;
      else
         return ResourceProvider.GetEnum( typeParameterName, val );
   }
}

枚举定义:

[TypeConverter( typeof( EnumTypeConverter<MyEnum> ) )]
public enum MyEnum
{
   Unknown = 0,
   SomeValue = 1,
   SomeOtherValue = 2
}

【问题讨论】:

    标签: c# wpf datagrid typeconverter expandoobject


    【解决方案1】:

    Use a value converter。无论如何,这是一种更传统的方法,它不依赖于反射在运行时被调用。

    public class MyEnumLocalizationConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var e = (MyEnum)value;
    
            var converted = "";
    
            //  Do whatever the type converter now does
    
            return converted;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    XAML:

    <Window.Resources>
        <!-- ... -->
    
        <local:MyEnumLocalizationConverter x:Key="MyEnumLocalizer" />
    
        <!-- ... -->
    </Window.Resources>
    
    <!-- ... -->
    
        <DataGridTextColumn
            Binding="{Binding EnumProperty, Converter={StaticResource MyEnumLocalizer}}"
            />
    

    如果你分享一些 XAML,我可以给你看

    【讨论】:

    • 我添加了一些实现细节,包括 XAML。我不确定 ValueConvert 是否适合我的情况。该实现包含大量枚举,并且 valueconverter 似乎特定于单一类型。是否可以定义通用版本?
    • @c__k 您可以保留类型转换器并编写一个通用值转换器,该转换器使用反射来获得正确的类型转换器。我认为这就是 XAML 之前使用类型转换器为您所做的事情的本质,当时它有一个类型化的属性作为绑定源。
    • 我试图让它工作几个小时,但最终放弃了。问题是我必须将转换器绑定到所有列,因为在编译时不知道可能出现枚举类型的列及其名称。我最终在运行时创建了一个类型并使用它而不是 ExpandoObject。
    • @c__k 是的,我没想到那么远。在运行时创建类型!哇。
    猜你喜欢
    • 1970-01-01
    • 2021-05-05
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    • 2016-04-13
    • 2014-03-02
    相关资源
    最近更新 更多