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

时间:2009-08-13 13:52:13

标签: .net winforms data-binding dataset checkbox

在Windows窗体(.NET 2.0,Visual Studio 2005 SP1)中:我有一个类型为DataSet的列,其类型为System.Boolean,可以为空,默认值为{{1 }}。我有一个DBNull,其中包含一个Form控件,我希望将其绑定到之前的列值。

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

    Parse
  • 我尝试在代码中创建自定义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 }; 实例,附加我的事件处理程序并将其添加到Binding绑定:事件处理程序仍然永远不会被调用...

    CheckBox

作为注释:Binding b=new Binding("CheckState", _BindingSource, "MyColumn", false, DataSourceUpdateMode.OnPropertyChanged, DBNull.Value); 值仅在来自DBNull时才可接受(这意味着该值从未设置过)。但是,用户应该只能通过DataSet将值设置为TrueFalse

供参考,以下是解析和格式化方法的代码:

CheckBox

2 个答案:

答案 0 :(得分:7)

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

不幸的是我没有可用的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--;
        }
    }
}


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及更高版本。

答案 1 :(得分:1)

我知道的简单方法是从CheckBox类派生,添加“DataValue”属性,它可以处理DBNull值并将数据绑定到“DataValue”属性:

public class DataCheckBox : CheckBox {
    public virtual object DataValue {
        get { return this.Checked; }
        set {
            if ( value == null || value is DBNull ) {
                this.CheckState = CheckState.Indeterminate;
            }
            else {
                this.Checked = (bool)value;
            }
        }
    }
}