Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Winforms data binding: Can a TypeConverter be used instead of the Format/Parse events?

In a Winforms form, I want to provide visual cues to the user when an input field contains an invalid value. To that end, I want to bind the ForeColor property of a input field's label to the (boolean) IsPropertyValid property of the underlying model such that the label turns red when IsPropertyValid == false.

What I currently have is an event handler for the binding's Format event:

Controls["dateOfBirthLabel"].DataBindings["ForeColor"].Format += convertBoolToColor;
// (dateOfBirthLabel.ForeColor is bound to a boolean IsDateOfBirthValid property.)

void convertBoolToColor(object sender, ConvertEventArgs e)
{
    e.Value = (bool)e.Value ? Color.Black : Color.Red;
}

If I wanted to do this in WPF, I suppose I would specify a custom value converter (bool to Color) directly with the binding in the XAML. Most importantly, I wouldn't have to refer to a specific control via its name.

I would like to do the same thing with my Winforms form. Ideally, I could specify a TypeConverter object for a particular binding directly in the Forms Designer. Is this possible?

like image 983
stakx - no longer contributing Avatar asked Aug 07 '10 11:08

stakx - no longer contributing


1 Answers

My previous answer (now deleted) was incorrect: This can be done, using a custom TypeConverter.

First, one needs a suitable converter. (Unlike with XAML, one does not implement a IValueConverter, but derive from TypeConverter.) For example:

// using System;
// using System.ComponentModel;
// using System.Drawing;
// using System.Globalization;

sealed class BooleanToColorConverter : TypeConverter
{
    public override bool CanConvertTo(ITypeDescriptorContext context,
                                      Type destinationType)
    {
        return destinationType == typeof(Color);
    }

    public override object ConvertTo(ITypeDescriptorContext context,
                                     CultureInfo culture,
                                     object value, 
                                     Type destinationType)
    {
        return (bool)value ? Color.Green : Color.Red;
    }
}

Next, (and also unlike with XAML data binding,) this converter is not applied to the binding itself; it must be attached to the data source's property using the [TypeConverter] attribute:

// using System.ComponentModel;

partial class DataSource : INotifyPropertyChanged
{
    [TypeConverter(typeof(BooleanToColorConverter))] // <-- add this! 
    public bool IsValid { get { … } set { … } }
}

Finally, formatting must be enabled on the data binding:

// Control control = …;
// DataSource dataSource = …;

control.DataBindings.Add("ForeColor", dataSource, "IsValid", formattingEnabled: true);
//                                                           ^^^^^^^^^^^^^^^^^^^^^^^

Note that this example only deals with one-way (data source to control) data binding. For two-way data binding, you would additionally have to override the TypeConverter.ConvertFrom and TypeConverter.CanConvertFrom methods.

like image 86
stakx - no longer contributing Avatar answered Nov 13 '22 16:11

stakx - no longer contributing