如何绑定一个复选框,一个布尔类型DbColumn是可空?布尔、绑定、复选框、类型

2023-09-04 01:03:46 作者:两岁可萌了

在Windows窗体(.NET 2.0,Visual Studio 2005的SP1):我有一个类型的数据集,与一列哪种类型系统。布尔,它是可空的,哪些默认值为的DBNull 。我有一个表格,包含复选框控件,我想绑定到现有列的值。

在我试图对检查属性绑定到通过设计师列:它的伟大工程,只有当该列的默认值设置为

我试图通过设计师的的CheckState 属性的列绑定,以及将自己的格式解析事件处理程序,但他们从来没有得到所谓:

  b.Format + =委托(对象发件人,ConvertEventArgs CEvent的){
    cevent.Value = DoFormat((的CheckState)cevent.Value); //比照问题结束
};
b.Parse + =委托(对象发件人,ConvertEventArgs CEvent的){
    cevent.Value = DoParse(cevent.Value); //比照问题结束
};
 

我试图创建一个自定义的绑定实例在code,附上我的事件处理程序,并把它添加到复选框绑定:在事件处理程序仍然没有得到所谓...

 绑定B =新的绑定(的CheckState,_BindingSource,根据MyColumn,假的,DataSourceUpdateMode.OnPropertyChanged,的DBNull.Value);
 
上百张入库单几分钟就可以生成发票 自动批量结算不再是空想

作为一个说明:一个的DBNull 值是可以接受的,只有当从的DataSet未来(这意味着该值从未被设置)。但是,用户应该只能够将该值设置为通过复选框

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

 内部静态的CheckState DoParse(对象的值)
{
    如果((价值== NULL)||(价值为DBNull))
        返回CheckState.Indeterminate;

    布尔V = Convert.ToBoolean(值);
    返程(ΔVCheckState.Checked:CheckState.Unchecked);
}

内部静态对象DoFormat(的CheckState值)
{
    开关(值)
    {
    案例CheckState.Checked:
        返回true;
    案例CheckState.Indeterminate:
        返回的DBNull.Value;
    案例CheckState.Unchecked:
        返回false;
    }

    返回null;
}
 

解决方案

您是否尝试过绑定CheckBox.CheckState到的DataColumn不附带分析和格式化事件或绑定搞乱?

不幸的是我没有的Visual Studio 2005提供了一个实例,但我聚集在Visual Studio 2008中的快速形式,它做的完全您指定的内容:

  

作为一个说明:一为DBNull值从DataSet到来时才可以接受的(这意味着价值从未被设置)。但是,用户应该只能够通过复选框,将该值设置为真或假。

我可以解析,格式或绑定在你的方式,或者它可能是Windows窗体表现不同,2008年比2005年

更新8月18日: 它适用于Visual Studio 2005中也均通过设计师,并通过code。 这里的code,演示它的工作:

 
使用系统;
使用System.Data这;
使用System.Drawing中;
使用System.Windows.Forms的;

命名空间WindowsFormsApplication1 {
    公共部分Form1类:表格{
        数据表表=新的DataTable();
        公共Form1中(){
            的InitializeComponent();

            //创建表结构
            table.Columns.Add(姓名,typeof运算(字符串));
            table.Columns.Add(根据MyColumn的typeof(布尔));

            //填充表与一些东西
            的for(int i = 0; I&其中5;我++){
                table.Rows.Add(i.ToString());
            }

            //创建控件,并将它们在表单上。
            文本框的textBox =新文本框();
            textBox.Location =新点(10,10);
            textBox.DataBindings.Add(文本,表中的姓名);

            复选框复选框=新的复选框();
            checkBox.Left = textBox.Left;
            checkBox.Top = textBox.Bottom + 10;

            //如果没有在最后一个参数属实,这将无法正常工作。
            checkBox.DataBindings.Add(的CheckState,表,根据MyColumn,真正的);

            按钮previous =新按钮();
            previous.Text =;
            next.Top = previous.Top;
            next.Left = previous.Right + 5;
            next.Click + =新的EventHandler(next_Click);

            this.Controls.AddRange(新的控制[] {文本框中复选框,previous,接下来});
        }

        无效next_Click(对象发件人,EventArgs的){
            this.BindingContext [this.table] .Position ++;
        }

        虚空previous_Click(对象发件人,EventArgs的){
            this.BindingContext [this.table] .Position--;
        }
    }
}

 

更新8月23日:

为什么它的工作原理

结合有一个私人方法所谓FormatObject它负责获得的值从数据源适合于被显示在控制未来的重新presentation

当启用了格式化,Binding.FormatObject()将通过,将调用您对Binding.Format事件最终处理一个code路径运行。如果任何的处理程序改变从数据源到通过ConvertEventArgs.Value控制被传播的值,则该值将被使用。否则,它会调用默认的格式称为FormatObject一个内部类称为System.Windows.Forms.Formatter。

在源$ C ​​$ C状态的评论:

内FormatObjectInternal()真正的转换工作情况

有关FormatObjectInternal状态的评论:

执行一些特殊情况下的转换(如布尔值的CheckState)

里面FormatObjectInternal它检查是否值从数据源即将为空或为DBNull,如果是这样的话,它会检查,看看是否被绑定的属性的类型的CheckState的。如果是这样的话,则返回CheckState.Indeterminate

正如你所看到的,这是这样一个共同的情况下,这是一个惊喜它没有在Windows窗体工作1.x的幸运的是,它固定在2.0及以后。

In Windows Forms (.NET 2.0, Visual Studio 2005 SP1) : I have a typed DataSet, with a column which type is System.Boolean, which is nullable and which default value is DBNull. I have a Form, containing a CheckBox control that I want to bind to the prior column value.

I have tried to bind the Checked property to the column via the designer : it works great, only if the default value for the column is set to either True or False.

I have tried to bind the CheckState property to the column via the designer, and attaching my own Format and Parse event handlers but they never get called :

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

I have tried to create a custom Binding instance in the code, attach my event handlers and add it to the CheckBox bindings : the event handlers are still never get called...

Binding b=new Binding("CheckState", _BindingSource, "MyColumn", false, DataSourceUpdateMode.OnPropertyChanged, DBNull.Value);

As a note : a DBNull value is acceptable only when coming from the DataSet (it means the value has never been set). But the user should only be able to set the value to True or False via the CheckBox.

For reference, here is the code of the parsing and formatting methods :

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

解决方案

Have you tried binding CheckBox.CheckState to the DataColumn without attaching to Parse and Format events or messing with the Binding?

Unfortunately I don’t have an instance of Visual Studio 2005 available but I assembled a quick form in Visual Studio 2008 and it did exactly what you specified:

As a note : a DBNull value is acceptable only when coming from the DataSet (it means the value has never been set). But the user should only be able to set the value to True or False via the CheckBox.

I may be the Parse, Format or Binding getting in your way or it may be that Windows Forms behaves differently in 2008 than in 2005

UPDATE Aug 18: It works on Visual Studio 2005 too both through the designer and through code. Here's the code that demonstrates it working:


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

UPDATE Aug 23:

Why it works

Binding has a private method called FormatObject which is responsible for obtaining a representation of the value coming from the data source that is appropriate for being shown on the control.

When formatting is enabled, Binding.FormatObject() will run through a code path that will call eventual handlers you have for the Binding.Format event. If any handler changes the value being propagated from the data source to the control through ConvertEventArgs.Value, that value will be used. Otherwise, it will call a default formatter called FormatObject on an internal class called System.Windows.Forms.Formatter.

The comments on the source code state:

"The real conversion work happens inside FormatObjectInternal()"

The comments for FormatObjectInternal state:

"Performs some special-case conversions (eg. Boolean to CheckState)"

Inside of FormatObjectInternal it checks to see if the value coming from the data source is null or DBNull and if that is the case, it checks to see if the type of the property being bound is of CheckState. If that is the case, it returns CheckState.Indeterminate.

As you can see, this is such a common case that it is a surprise it didn't work on Windows Forms 1.x. Luckily, the fixed it on 2.0 and beyond.

 
精彩推荐
图片推荐