TypeConverter不使用ExpandoObject和DataGrid

时间:2017-06-07 14:26:58

标签: c# wpf datagrid typeconverter expandoobject

我有一个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属性的子集,具体取决于select语句。

一切正常,但枚举属性的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>

TYPE CONVERTER:

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
}

1 个答案:

答案 0 :(得分:0)

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,我可以告诉你