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 spe开发者_运维技巧cify 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?
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.
c.DataBindings.Add("Checked", dataSource, dataMember, true, DataSourceUpdateMode.OnPropertyChanged );
class Someclass
{
[TypeConverter(typeof(IntBoolConverter))]
public int p_isEnable
{
get { return nc_isEnable; }
set { m_isEnable= value); }
}
}
public class IntBoolConverter:TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(bool))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(int))
{
return true;
}
return base.CanConvertFrom(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is bool)
{
var objectToInt = value.ObjectToBool();
return objectToInt;
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(bool))
{
return value.ObjectToBool();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
精彩评论