自定义 WinForms 数据绑定与转换器不适用于可空类型(双精度?)

2024-02-29

在我的 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


事实上,错误不在您的代码中,而是在您下载的代码中(CustomBinding)。修改构造函数成为

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;
}

问题就会得到解决。最重要的部分是Binding.FormatingEnabled必须是true为了使这一切正常工作(请注意基本调用的最后一个参数,但您也可以稍后设置它)。另请注意,我删除了

this.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;

线。默认值为OnValidation适用于任何控制。OnPropertyChanged适用于立即更新控件,例如复选框、单选按钮和不可编辑的组合框。无论如何,最好将设置此属性的责任留给类的用户。

与问题无关的旁注:您最好不要剥离无效字符,并让异常在您的内部抛出ConvertBack方法,否则如果用户键入“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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义 WinForms 数据绑定与转换器不适用于可空类型(双精度?) 的相关文章

随机推荐

  • 如何创建文件并写入文件?

    最简单的方法是什么用 Java 创建并写入 文本 文件 https docs oracle com javase tutorial essential io file html 请注意 下面的每个代码示例都可能会抛出异常IOExceptio
  • 将一组新数据写入 Plist 而不是覆盖它

    我试图获取一个 plist 来存储多组数据 但每次保存 使用 ActionSheet 中的按钮 时 它都会覆盖前一组数据 我想添加多个 朋友 及其数据 我不太热衷于使用 Core Data 所以我想知道如何使用 Plist 来做到这一点 这
  • NSAsynchronousFetchRequest - 应该在主线程上显式完成更新

    我正在创建一个 NSAsynchronousFetchRequest 其中有一个完成块 我见过各种示例 其中一些包括在主线程上使用调度队列 而另一些则没有 例如 Ray Wenderlich 核心数据手册不会在主线程上调用结果 执行结果时我
  • React Native 堆栈跟踪

    I have React Native App与 Firebase Crashlytics 关联 问题是 firebase 发送不可读的堆栈跟踪 如下所示 有任何方法可以读取此类错误 我只想知道什么时候抛出错误 这是我的堆栈跟踪 致命异常
  • 启用服务器端加密的跨账户访问 AWS SQS

    上下文 AWS 账户 2 中有一个 API 将 SQS url 作为其输入之一并向其发布输出 帐户 1 的所有者希望将此 API 与他自己的 SQS 队列一起使用 账户 1 有一个启用了 SSE KMS 的 SQS 队列 账户 1 的所有者
  • 构建 Qt - NMAKE:致命错误 U1077:“cd”:返回代码“0x2”

    我正在尝试使用 msvc2015 构建带有静态链接的 Qt5 5 但出现以下错误 实际上有很多错误 但我只列出了一些 它们都完全相同 K Archivos de programa Microsoft Visual Studio 14 0 V
  • pack://application:,/ResourceFile.xaml 永远不会工作

    我从来没有能够让资源字典的这种参考格式发挥作用 我缺少什么 设想 创建并组装一些用户控件 在根目录下有所说的文件 根 主题 ColorThemes xaml ColorThemes xaml 文件的构建操作设置为Resource http
  • 覆盖本地资源字典中的系统颜色

    我试图隐藏指示 WPF 中选择的视觉提示ListBox 这个答案 https stackoverflow com questions 4343793 how to disable highlighting on listbox but ke
  • 使用多个类实现一个接口

    这个问题是在一次采访中问我的 我厌倦了在这里谷歌搜索 我有一个包含 100 个方法的接口 我不想在一个类中实现所有这 100 个方法 有没有一种方法可以通过使用多个类来实现这 100 个方法而不重复实现 例如 A 类 仅 实现前 10 个方
  • Android JSON HttpClient 使用 HttpResponse 将数据发送到 PHP 服务器

    我目前正在尝试从 Android 应用程序发送一些数据到 php 服务器 两者都由我控制 应用程序中的表单上收集了大量数据 这些数据被写入数据库 这一切都有效 在我的主代码中 首先我创建一个 JSONObject 在本例中我已将其删减 JS
  • Scala lambda 函数与 map 函数

    我定义以下变量x val x Array 3 2 4 5 它的类型是Array Int Int 当我执行以下操作时 x map a Int b Int gt a b 我收到以下错误 console 28 error type mismatc
  • .Net MVC - 从视图中访问数据库不仅仅是糟糕的做法? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我见过一些开发人员实例化从视图内访问数据库的模型 通常 当他们想要访问 html 部分时 他们会这样做 并且他们只是在视图中创建一个新的视图模型
  • 有没有办法在 Scala 中使用“type”字作为变量名?

    在我的实践中 变量 参数经常用于存储某种类型 通常作为枚举值 在名称中指定实体类通常是没有意义的 就像当函数仅用于处理用户时的 userType 一样 有没有办法可以使用 类型 一词来满足我的需求 而不是使用 tipe kind somet
  • 如何从多维数组中提取列?

    有谁知道如何在Python中从多维数组中提取列 gt gt gt import numpy as np gt gt gt A np array 1 2 3 4 5 6 7 8 gt gt gt A array 1 2 3 4 5 6 7 8
  • 如何在 Struts 2 中的 JSP 页面上显示数据库记录列表(通过 Hibernate 检索)?

    我正在尝试使用 Hibernate 在 Struts 2 中的 JSP 页面中显示数据库记录 我已经成功完成检索部分 但无论我做什么 我似乎都无法在JSP页面中显示数据 我尝试过在互联网上找到的各种解决方案 但无法理解似乎是什么问题 我可以
  • 在端口 80 上运行 Sinatra

    我安装了 Sinatra 它可以工作 但默认使用端口 4567 我希望它在端口 80 上运行 为了让它在端口 80 上工作 我尝试了以下方法 require rubygems require rack handler webrick req
  • 为什么光线追踪器将球体渲染为椭圆形?

    在过去的几天里 我第一次破解了光线追踪器 然而 有一些怪癖困扰着我 我真的不知道如何锻炼 从一开始就存在的一个是场景中球体的形状 渲染时 它们实际上看起来像椭圆形 当然 场景中有透视 但最终的形状仍然显得奇怪 我附上了渲染示例 我遇到的问题
  • 什么时候应该直接调用 Promise.resolve() ?

    我见过原生 ES6Promise resolve 可以直接调用 作为静态方法 Facebook 在他们的 Flux 示例中就是这样使用它的 但什么情况下我应该这样做呢 排队买东西 或者代替使用window setTimeout 你应该打电话
  • PHP 中有元组吗?

    我知道在 Python 和其他语言中 我们可以访问元组 以便在语义或其他方面更好地促进数据的结构化 我的问题是 PHP 有元组吗 如果没有 最近的设施是什么 PHP 中的数组可以像元组一样使用 one dimensional mixed d
  • 自定义 WinForms 数据绑定与转换器不适用于可空类型(双精度?)

    在我的 WinForms 应用程序中我实现了支持值转换器的自定义数据绑定 https reynaerta wordpress com 2012 12 17 ivalueconverter for binding in winfroms 类似