Привязка ReactiveList‹enum› к полю со списком

Я видел множество решений для привязки ReactiveList к элементу управления ComboBox в WPF, чтобы элемент управления отображал описания элементов перечисления. Все эти решения используют стандартный TypeConverter и привязку в XAML, но я использую ReactiveUI, поэтому я хочу сделать привязки в коде позади. Без какого-либо преобразования я получаю необработанные значения перечисления в виде строк, а не их описаний, поэтому, по крайней мере, я знаю, что привязка работает правильно, но я не разобрался с преобразованием.

Я почти уверен, что мне нужно использовать IBindingTypeConverter (и зарегистрировать его с помощью Splat), но я не могу найти правильную комбинацию toType и fromType в моем конвертере, чтобы это произошло. Я пробовал следующее с частичным успехом:

public class MyEnumToStringConverter : IBindingTypeConverter
{
    public int GetAffinityForObjects(Type fromType, Type toType)
    {
        if (fromType == tyepof(ReactiveList<MyEnumType>))
        {
            return 100;
        }
        return 0;
    }

    public bool TryConvert(object from, Type toType, object conversionHint, out object result)
    {
        ...
    }
}

В отладчике GetAffinityForObjects() срабатывает и возвращает 100 во время вызова для привязки ItemsSource ComboBox, но TryConvert никогда не вызывается.

Может ли кто-нибудь привести хороший пример того, как сделать это правильно в ReactiveUI?


person Josh K    schedule 02.09.2015    source источник
comment
чтобы получить что-то вроде описания, я использую комбинацию атрибута DisplayName и метода расширения, работает с любым приложением и с xaml IBindingTypeConverter   -  person mijail    schedule 02.09.2015
comment
Суть здесь в том, чтобы выполнить привязку в исходном коде, а не в XAML.   -  person Josh K    schedule 09.09.2015


Ответы (1)


Просто идея, это много всего: Display это часть пространства имен System.ComponentModel.DataAnnotations, но вы можете использовать другой и просто изменить DisplayName метод

public enum CoolEnum {
    [Display(Name="Value 1")]
    Value1,
    [Display(Name="Value 2")]
    Value2,
}

public static class EnumExtensions
{
    public static string DisplayName(this Enum value)
    {
        Type enumType = value.GetType();
        var enumValue = Enum.GetName(enumType, value);
        MemberInfo member = enumType.GetMember(enumValue)[0];

        var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
        var outString = ((DisplayAttribute)attrs[0]).Name != null ? ((DisplayAttribute)attrs[0]).Name : enumValue; //TODO Null check

        if (((DisplayAttribute)attrs[0]).ResourceType != null)
        {
            outString = ((DisplayAttribute)attrs[0]).GetName();
        }

        return outString;
    }
}

Используйте это так:

var enumValue = CoolEnum.Value1;
var displayValue = enumValue.DisplayName();

В XAML можно использовать ValueConverter

public class EnumToDisplayName : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        try 
        {
            var enumValue = (CoolEnum)value;
            return enumValue.DisplayName();
        }
        catch (Exception){
        }
        return string.Empty;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return System.Windows.DependencyProperty.UnsetValue;
    }
}

Внутри материала XAML, где вы связываете данные, сопоставляете преобразователь как ресурс и используете его:

<UserControl.Resources>
    <local:EnumToDisplayValue x:Key="enumToDisplayValue" />
</UserControl.Resources>

Text="{Binding enumValue, Converter={StaticResource enumToDisplayValue}}"

Просто идея для начала, получайте удовольствие от кодирования :)

person mijail    schedule 02.09.2015
comment
Суть вопроса заключалась в том, чтобы сделать это таким образом, чтобы можно было использовать методы привязки ReactiveUI в коде, а не привязки в XAML. Хотя ваша реализация будет работать, она не удовлетворяет требованию удаления привязок из XAML и не является реализацией на основе ReactiveUI. - person Josh K; 09.09.2015