在我的 WinForms 应用程序中我实现了支持值转换器的自定义数据绑定 https://reynaerta.wordpress.com/2012/12/17/ivalueconverter-for-binding-in-winfroms/,类似于WPF。
该示例有一个新的绑定类,该类派生自Binding
并允许附加自定义转换器:
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);
}
}
还有界面IValueConverter
类似于WPF的界面:
public interface IValueConverter
{
object Convert(object value, Type targetType, object parameter, CultureInfo culture);
object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
}
这样我就可以将自己的转换器附加到任何(双向)绑定。到目前为止我已经建立了一个TimeSpanStringValueConverter
这允许我绑定一个TimeSpan
字段到文本框以及InvertBooleanValueConverter
将布尔字段的相反值绑定到任何控件的任何布尔属性。他们按预期工作!
现在我想绑定该类型的属性double?
到文本框Text
场地。为此我写了这个转换器:
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;
}
}
我这样将它绑定到文本框:
this.textBox1.DataBindings.Add(new CustomBinding("Text", obj, "MyProperty", new NullableDoubleStringValueConverter())); // obj is the data context object
当我在中设置断点时ConvertBack
值转换器的方法我可以清楚地看到我的字符串在离开文本框后如何成功转换为可为空的双精度值。但是,与我的其他情况不同,它不会更新数据上下文对象。如果我在Convert
我的值转换器的方法我可以看到它将检索初始值MyProperty
更新时为空Text
离开后的文本框。因此,在其中输入任何数值后,我的文本框会变空。
我的问题是:为什么?我怎样才能让它与可空类型一起工作(double?
)?如果我改变类型MyProperty
在数据上下文对象中double
它会接受我改变的值。不幸的是我需要可为空的支持。因此,当将文本框留空时,我想存储 null 并在值为 null 时显示空文本框。
问题案例解决方案下载 https://dl.dropboxusercontent.com/u/55589036/zzzOther/NullableDoubleStringValueConverterProblem.zip