【问题标题】:EF: Databinding checkbox to nullable int valueEF:数据绑定复选框到可为空的 int 值
【发布时间】:2016-10-28 17:32:32
【问题描述】:

我想知道在 Winforms 中绑定到 CheckBox 时是否有处理 int 类型的可空值的方法。

以下面的示例类为例:

public class TestClass
{
    public Nullable<int> NULLABLE_INT_VALUE { get; set; }
    public int NON_NULLABLE_VALUE { get; set; }
}

我有一个继承自标准复选框的组件,它允许您传递一个对象(即类实例)和一个属性名称,并将针对该复选框设置一个 DataBinding:

public void FSetDataBinding(object BindingObject, string FieldName)
{
    Binding ControlBinding = new Binding("Checked", BindingObject, FieldName) { NullValue = false };
    ControlBinding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
    ControlBinding.Format += (s, e) => { e.Value = e.Value.ToString() == "1"; };
    ControlBinding.Parse += FormDBCheckBox_Parse;
    DataBindings.Add(ControlBinding);
}

private void FormDBCheckBox_Parse(object sender, ConvertEventArgs e)
{
    if((bool)(e.Value))
    {
        e.Value = "1";
    }
    else
    {
        e.Value = "0";
    }
}

如果我创建两个复选框控件(分别为chkNullableValuechkNonNullableValue),我可以将它们绑定到一个TestClass(我们在这里假设TestClass 是数据库表的EF 版本:

TestClass IAmATest = new TestClass() { NULLABLE_INT_VALUE = 1, NON_NULLABLE_VALUE = 0 }
chkNullableValue.FSetDataBinding(IAmATest, "NULLABLE_INT_VALUE");
chkNonNullableValue.FSetDataBinding(IAmATest, "NON_NULLABLE_VALUE");

两个属性都来自同一个对象,并且以完全相同的方式绑定;但是,当我尝试检查绑定到可为空值的框时,由于某种原因,(set;) 访问器永远不会与该属性相撞。发生的情况是,在表单上,​​该框似乎已选中;但是,由于该框的基础属性尚未更新,因此下次它格式化控件以进行显示时,e.Value 仍然是 "0",并且框将“取消选中”自身。这也意味着调用 SaveChanges() 不会更新该值,因为它在技术上从未更新过。

这里也需要注意: 是的,NullValue = falseBinding 的创建是对的;但是,在这种特定情况下,可为空的值已经具有 "0" 的值,因此实际上永远不会是 null(但它可能在其他情况下)。

对于不可为空的属性则相反,它的行为完全符合我的预期;当您选中表单上的框时,NON_NULLABLE_VALUE 的值将更新并设置为 "1" 作为FormDBCheckBox_Parse 的一部分,因此下次控件格式化自身时,ControlBinding.Format 返回"true" 和选中的属性相应地设置。

我认为,如果某物是一个标志(因此始终是“关闭”或“开启”),则不应允许空值针对数据库中的字段,因此最后我只是使值不可为空;但是,我想确切地了解为什么我在使用可空类型时遇到这么多麻烦,以防我将来需要将它用于其他任何事情。

【问题讨论】:

    标签: c# entity-framework checkbox data-binding


    【解决方案1】:

    首先,适用于intint? 的正确绑定配置:

    public void FSetDataBinding(object BindingObject, string FieldName)
    {
        Binding ControlBinding = new Binding("Checked", BindingObject, FieldName, true) { DataSourceNullValue = false };
        ControlBinding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
        DataBindings.Add(ControlBinding);
    }
    

    注意事项:

    • 始终将Binding.FormattingEnabled 属性设置为true(通过使用上述构造函数重载或属性设置器)。它正在修复一些为“向后兼容”而保留的旧数据绑定错误 - 不幸的是默认情况下。

    • 与文档相反,NullValue 是在设置数据源值之前转换为null 的控制值。而DataSourceNullValue是数据源值为null或为空时控件设置的值。所以你需要使用后者,否则当你取消选中绑定到nullable int的复选框时,该属性将设置为null

    • 您的Parse 方法不正确。在您的情况下,它应该将控制值(bool)转换为数据源值(intint?),同时将其转换为string。由于默认的 boolint 转换(反之亦然)完全符合您的要求,因此我刚刚删除了自定义 FormatParse

    【讨论】:

    • 非常感谢您的回答以及其他解释。我再次查看了 NullValue 和 DataSourceNullValue 在 Binding 上表示的内容,这说明了为什么事情不起作用。我还按照您的建议设置了 FormattingEnabled。
    • 另外,我需要保留 Parse 和 Format 过程,因为数据库中有一些字段是字符串,可以包含字符串值或“标志”(即设置;不是我的想法,但是,我必须使用它);所以我将 FSetDataBinding 更改为 FSetDataBinding where T : class 以允许我反映 BindingObject 并找到属性的类型并仅在绑定到字符串值时添加 Format / Parse,因为我仍然想要“0 " 和 "1" 值,而不是它们的字面值 "false" 和 "true" 进入数据库。
    • 好的,但至少在处理Parse 事件时,检查ConvertEventArgs.DesiredType 属性——如果它是typeof(string),然后做boolstring 的转换,如果不是——要么正确处理它,要么保持原样,这样就会发生默认转换。
    • 我认为这不是必需的(即我可以保持原样),因为我已将 FSetDataBinding 更改为仅在绑定属性是 typeof 时添加 Format 和 Parse 事件(细绳);因此,如果不是,则无论如何都不会调用 Parse 和 Format ,因为正如您所说,可以使用默认的 bool 到 int 的转换。
    猜你喜欢
    • 2013-07-13
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 2018-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多