Search code examples
c#wpftypeconverter

Can TypeConverters from WinForms be used in WPF?


C#, WPF. In a WPF application I have got classes originally from WinForms, which have TypeConverters and corresponding decorators. From the information I can find online it seems that TypeConverter is not universally supported and tends to be mainly used in Winforms. But I have not been able to find a clear and simple explanation of its scope/applicability in WPF.

I have created the following minimal example. Latitude and Longitude are doubles and I would like them to appear in an xceed PropertyGrid formatted as strings by (existing) TypeConverter. In the simplest case this formatting would be adding a degree symbol, but there are also conversions between different units of measurement.

Here the TypeConverter is clearly not being used. I see "1" and "2" in the PropertyGrid and "1" in the Textbox.

Should it work this way, or do I need to rewrite in a more WPF-centric way (e.g. ValueConverter:IValueConverter)?

<Window x:Class="PropertyGridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PropertyGridTest"
        xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel Orientation="Vertical">
            <xctk:PropertyGrid Name="propertyGrid"/>
            <TextBox Name="textBox" Text="{Binding Path=Latitude}"/>
        </StackPanel>
    </Grid>
</Window>

namespace PropertyGridTest
{

    public class Foo {
        [TypeConverter(typeof(DegreesTypeConverter))]
        public double Latitude { get; set; } = 1.0;
        [TypeConverter(typeof(DegreesTypeConverter))]
        public double Longitude { get; set; } = 2.0;
    }

    public partial class MainWindow : Window
    {
        Foo bar = new Foo();
        public  MainWindow()
        {
            InitializeComponent();
            propertyGrid.AutoGenerateProperties = true;
            propertyGrid.SelectedObject = bar;
            textBox.DataContext = bar;
        }
    }

    public class DegreesTypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return destinationType == typeof(string);
        }
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            return (value is string) ? 999.0 : 0.0;
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            return (destinationType == typeof(string)) ? "[formatted string]" : "";
        }
    }

}

Solution

  • Should it work this way, or do I need to rewrite in a more WPF-centric way (e.g. ValueConverter:IValueConverter)?

    Yes, WPF uses value converters to convert a value of a source property from one type to another. If you don't specify one, it will use a built-in converter which basically just calls ToString() on the value. The framework will not check if the data-bound property is decorated with a [TypeConverter] attribute.

    TypeConverters are however used to convert XAML strings to other types. Please refer the docs for more information about this.