Avalonia icon indicating copy to clipboard operation
Avalonia copied to clipboard

Custom TypeConverter Not Working

Open laolarou726 opened this issue 1 year ago • 5 comments

Describe the bug Custom TypeConvert does not have any effect

To Reproduce Steps to reproduce the behavior:

  1. Create a EnumTypeConverter
public class EnumDescriptionTypeConverter : EnumConverter
{
    public EnumDescriptionTypeConverter(Type type)
        : base(type)
    {
    }

    public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value,
        Type destinationType)
    {
        if (destinationType != typeof(string)) return base.ConvertTo(context, culture, value, destinationType);
        if (value == null) return string.Empty;

        var fi = value.GetType().GetField(value.ToString());
        if (fi == null) return string.Empty;

        var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 && !string.IsNullOrEmpty(attributes[0].Description)
            ? attributes[0].Description
            : value.ToString();
    }
}
  1. Create an Enum type with DescriptionAttribute
[TypeConverter(typeof(EnumDescriptionTypeConverter))]
public enum TestEnum
{
    [Description("Description for Item1")]
    Item1,

    [Description("Description for Item2")]
    Item2
}
  1. Bind this enum type to the view
public TestEnum Test => TestEnum.Item1;

<TextBlock Text="{Binding Test}"/>

Expected behavior The content of the TextBlock should be "Description for Item1". However, it shows "Item1"

Desktop (please complete the following information):

  • OS: Windows11
  • Version 0.10.17

laolarou726 avatar Jul 23 '22 16:07 laolarou726

Avalonia goes a "fast path" for "enun -> string" conversion here https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Base/Utilities/TypeUtilities.cs#L151

Proper behavior seems to be to read TypeDescriptor.GetConverter first. Or we can try to port DefaultValueConverter from WPF @grokys

Workaround should be simple enough, to use custom IValueConverter and get TypeDescriptor.GetConverter from type before converting.

maxkatz6 avatar Jul 27 '22 04:07 maxkatz6

TypeDescriptor.GetConverter works great for me. However, it is not the default behavior. I think making this a default behavior will be great. Maybe port DefaultValueConverter from WPF is a great idea!

laolarou726 avatar Jul 27 '22 09:07 laolarou726

Is there any workaround for the ComboBox binding? For example, if I bind an enum list to a ComboBox. How should I apply this type of converter to all the ComboBoxItem? @maxkatz6

laolarou726 avatar Aug 04 '22 23:08 laolarou726

Hi @laolarou726

I can think of several options here:

  • You can set ItemTemplate on your ComboBox and inside the ItemTemplate you can use your IValueConverter
  • You can implement IDataTemplate in your class and use this as your ItemTemplate, see https://docs.avaloniaui.net/docs/templates/implement-idatatemplate
  • You can wrap your enum values in a class or struct which will override ToString()

Happy coding Tim

timunie avatar Aug 05 '22 07:08 timunie

@timunie Thank you so much.

laolarou726 avatar Aug 06 '22 11:08 laolarou726