如何将CheckBox绑定到可以为空的bool类型的DbColumn?

Mac*_*Mac 4 .net data-binding checkbox dataset winforms

在Windows窗体(.NET 2.0,Visual Studio 2005 SP1)中:我有一个类型DataSet为type的列System.Boolean,可以为空,默认值为DBNull.我有一个Form,包含CheckBox我想要绑定到先前列值的控件.

  • 我试图Checked通过设计器将属性绑定到列:只有当列的默认值设置为True或时,它才能正常工作False.
  • 我试图CheckState通过设计器将属性绑定到列,并附加我自己的FormatParse事件处理程序,但它们永远不会被调用:

    b.Format+=delegate(object sender, ConvertEventArgs cevent) {
        cevent.Value=DoFormat((CheckState)cevent.Value); // cf. end of the question
    };
    b.Parse+=delegate(object sender, ConvertEventArgs cevent) {
        cevent.Value=DoParse(cevent.Value); // cf. end of the question
    };
    
    Run Code Online (Sandbox Code Playgroud)
  • 我试图Binding在代码中创建一个自定义实例,附加我的事件处理程序并将其添加到CheckBox绑定:事件处理程序仍然永远不会被调用...

    Binding b=new Binding("CheckState", _BindingSource, "MyColumn", false, DataSourceUpdateMode.OnPropertyChanged, DBNull.Value);
    
    Run Code Online (Sandbox Code Playgroud)

作为注释:DBNull只有当来自DataSet(这意味着从未设置过值)时,值才可接受.但是用户应该只能将值设置为TrueFalse通过CheckBox.

作为参考,这里是解析和格式化方法的代码:

internal static CheckState DoParse(object value)
{
    if ((value==null) || (value is DBNull))
        return CheckState.Indeterminate;

    bool v=Convert.ToBoolean(value);
    return (v ? CheckState.Checked : CheckState.Unchecked);
}

internal static object DoFormat(CheckState value)
{
    switch (value)
    {
    case CheckState.Checked:
        return true;
    case CheckState.Indeterminate:
        return DBNull.Value;
    case CheckState.Unchecked:
        return false;
    }

    return null;
}
Run Code Online (Sandbox Code Playgroud)

Alf*_*ers 7

您是否尝试将CheckBox.CheckState绑定到DataColumn而不附加Parse和Format事件或搞乱绑定?

不幸的是我没有可用的Visual Studio 2005实例,但是我在Visual Studio 2008中组装了一个快速表单,它完全符合您的指定:

注意:只有来自DataSet时才接受DBNull值(这意味着从未设置过该值).但是用户应该只能通过CheckBox将值设置为True或False.

我可能是Parse,Format或Binding妨碍你或者可能是Windows Forms在2008年的表现与2005年不同


更新8月18日: 它也可以通过设计器和代码在Visual Studio 2005上运行.这是演示它工作的代码:


using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        DataTable table = new DataTable();
        public Form1() {
            InitializeComponent();

            //Creates the table structure
            table.Columns.Add("Name", typeof(string));
            table.Columns.Add("MyColumn", typeof(bool));

            //Populates the table with some stuff
            for (int i = 0; i < 5; i++) {
                table.Rows.Add(i.ToString());
            }

            //Creates the controls and puts them on the form.
            TextBox textBox = new TextBox();
            textBox.Location = new Point(10, 10);
            textBox.DataBindings.Add("Text", table, "Name");

            CheckBox checkBox = new CheckBox();
            checkBox.Left = textBox.Left;
            checkBox.Top = textBox.Bottom + 10;

            //Without true on the last argument, it will not work properly.
            checkBox.DataBindings.Add("CheckState", table, "MyColumn", true);

            Button previous = new Button();
            previous.Text = "";
            next.Top = previous.Top;
            next.Left = previous.Right + 5;
            next.Click += new EventHandler(next_Click);

            this.Controls.AddRange(new Control[] { textBox, checkBox, previous, next });
        }

        void next_Click(object sender, EventArgs e) {
            this.BindingContext[this.table].Position++;
        }

        void previous_Click(object sender, EventArgs e) {
            this.BindingContext[this.table].Position--;
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

8月23日更新:

为什么会这样

Binding有一个名为FormatObject的私有方法,它负责获取适合在控件上显示的来自数据源的值的表示.

启用格式化后,Binding.FormatObject()将通过代码路径运行,该路径将调用您对Binding.Format事件的最终处理程序.如果任何处理程序通过ConvertEventArgs.Value更改从数据源传播到控件的值,则将使用该值.否则,它将在名为System.Windows.Forms.Formatter的内部类上调用名为FormatObject的默认格式化程序.

对源代码状态的评论:

"真正的转换工作发生在FormatObjectInternal()中"

FormatObjectInternal状态的注释:

"执行一些特殊情况转换(例如布尔到CheckState)"

在FormatObjectInternal内部,它检查来自数据源的值是否为null或DBNull,如果是这种情况,它会检查绑定的属性的类型是否为CheckState.如果是这种情况,则返回CheckState.Indeterminate.

正如您所看到的,这是一个常见的情况,它在Windows Forms 1.x上无效.幸运的是,它固定在2.0及更高版本.