c# - Custom WinForms data binding with converter not working on nullable type (double?) -
in winforms application implemented custom data binding support value converters, similar wpf.
the sample has new binding class derives binding
, allows attach custom converter:
public class custombinding : binding { private readonly ivalueconverter _converter; private readonly object _converterparameter; private readonly cultureinfo _converterculture; public custombinding(string propertyname, object datasource, string datamember, ivalueconverter valueconverter, cultureinfo culture, object converterparameter = null) : base(propertyname, datasource, datamember) { if (valueconverter != null) this._converter = valueconverter; this.datasourceupdatemode = datasourceupdatemode.onpropertychanged; this.formattingenabled = false; this._converterculture = culture; this._converterparameter = converterparameter; } public custombinding(string propertyname, object datasource, string datamember, ivalueconverter valueconverter, object converterparameter = null) : base(propertyname, datasource, datamember) { if (valueconverter != null) this._converter = valueconverter; this._converterculture = thread.currentthread.currentuiculture; this._converterparameter = converterparameter; } protected override void onformat(converteventargs cevent) { if (this._converter != null) { var converterdvalue = this._converter.convert(cevent.value, cevent.desiredtype, _converterparameter, _converterculture); cevent.value = converterdvalue; } else base.onformat(cevent); } protected override void onparse(converteventargs cevent) { if (this._converter != null) { var converterdvalue = this._converter.convertback(cevent.value, cevent.desiredtype, _converterparameter, _converterculture); cevent.value = converterdvalue; } else base.onparse(cevent); } }
there interface ivalueconverter
similar interface of wpf:
public interface ivalueconverter { object convert(object value, type targettype, object parameter, cultureinfo culture); object convertback(object value, type targettype, object parameter, cultureinfo culture); }
with i'm able attach own converter (two-way) binding. far i've built timespanstringvalueconverter
allows me bind timespan
field textbox invertbooleanvalueconverter
bind opposite of boolean field boolean property of control. work expected!
now want bind property of type double?
textbox text
field. wrote converter:
public class nullabledoublestringvalueconverter : ivalueconverter { public object convert(object value, type targettype, object parameter, system.globalization.cultureinfo culture) { return value != null ? ((double)value).tostring(culture) : string.empty; } public object convertback(object value, type targettype, object parameter, system.globalization.cultureinfo culture) { string text = regex.replace((string)value, @"[^0-9" + culture.numberformat.numberdecimalseparator + @"]", ""); if (text == string.empty) { return null; } double convertedvalue; if (double.tryparse(text, numberstyles.any, culture, out convertedvalue)) { return (double?)convertedvalue; } return null; } }
and bind textbox way:
this.textbox1.databindings.add(new custombinding("text", obj, "myproperty", new nullabledoublestringvalueconverter())); // obj data context object
when set break point in convertback
method of value converter can see how string converted nullable double value after leaving textbox, successfully. however, instead of other cases, not update data context object. , if set break point in convert
method of value converter can see retrieve initial value of myproperty
null when updating text
of textbox after leaving it. so, textbox gets empty after typing numeric value in it.
my question is: why? , how can make work nullable types (double?
)? if change type of myproperty
in data context object double
accept changed value. unfortunately need nullable support. when leaving textbox empty want store null showing empty text box, when value null.
in fact, bug not in code, in 1 have downloaded (custombinding
). modify constructors become
public custombinding(string propertyname, object datasource, string datamember, ivalueconverter valueconverter, object converterparameter = null) : this(propertyname, datasource, datamember, valueconverter, thread.currentthread.currentuiculture, converterparameter) { } public custombinding(string propertyname, object datasource, string datamember, ivalueconverter valueconverter, cultureinfo culture, object converterparameter = null) : base(propertyname, datasource, datamember, true) { this._converter = valueconverter; this._converterculture = culture; this._converterparameter = converterparameter; }
and problem solved. essential part binding.formatingenabled
must true
in order work (note last argument base call, can set later too). note removed
this.datasourceupdatemode = datasourceupdatemode.onpropertychanged;
line. default value onvalidation
applicable control. onpropertychanged
applicable immediate update controls check boxes, radio buttons , non editable combo boxes. in case, better leave responsibility of setting property user of class.
a side note unrelated question: you'd better off not stripping invalid characters , let exception thrown inside convertback
method, otherwise weird input values if user types instance "1-3"
public object convertback(object value, type targettype, object parameter, system.globalization.cultureinfo culture) { var text = value != null ? ((string)value).trim() : null; return !string.isnullorempty(text) ? (object)double.parse(text, numberstyles.any, culture) : null; }
Comments
Post a Comment