У меня есть класс Poco
, в котором одно свойство является типом перечисления.
Чтобы сделать свойство перечисления локализуемым на уровне пользовательского интерфейса (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 ) );
Я не знаю, что происходит внутри DataGrid WPF. У меня сложилось впечатление, что он по какой-то причине просто вызывает 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
}