如何绑定一个CheckBox到bool类型的DbColumn是可空的? [英] How to bind a CheckBox to a bool typed DbColumn that is nullable?

查看:938
本文介绍了如何绑定一个CheckBox到bool类型的DbColumn是可空的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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




  • 我试图通过设计器将 Checked 属性绑定到列:it works great,只要列的默认值设置为 True False

  • 我已尝试通过设计器将 CheckState 属性绑定到列,并附加我自己的格式 Parse 事件处理程序,但是它们从未被调用:

      b .Format + = delegate(object sender,ConvertEventArgs cevent){
    cevent.Value = DoFormat((CheckState)cevent.Value); // cf.结束问题
    };
    b.Parse + = delegate(object sender,ConvertEventArgs cevent){
    cevent.Value = DoParse(cevent.Value); // cf.结束问题
    };


  • 我尝试创建自定义绑定代码中的实例,附加我的事件处理程序并将其添加到 CheckBox 绑定:事件处理程序仍然从未被调用...

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




注意: DBNull 值只有在来自 DataSet (这意味着该值从未设置)时才可以接受。但用户应该只能通过复选框将值设置为 True False



下面是解析和格式化方法的代码:

 内部静态CheckState DoParse(对象值)
{
if((value == null)||(value is DBNull))
return CheckState 。不定;

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

内部静态对象DoFormat(CheckState值)
{
switch(value)
{
case CheckState.Checked:
return true;
case CheckState.Indeterminate:
return DBNull.Value;
case CheckState.Unchecked:
return false;
}

return null;
}


解决方案

CheckState到DataColumn而不附加到解析和格式事件或乱七八糟?



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


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


我可能是解析,绑定得到的方式,或可能是Windows窗体在2008年比2005年不同的行为






18:
它也通过设计器和代码在Visual Studio 2005上工作。
下面是演示它工作的代码:

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

命名空间WindowsFormsApplication1 {
public partial class Form1:Form {
DataTable table = new DataTable();
public Form1(){
InitializeComponent();

//创建表结构
table.Columns.Add(Name,typeof(string));
table.Columns.Add(MyColumn,typeof(bool));

//用一些东西填充表
for(int i = 0; i< 5; i ++){
table.Rows.Add(i.ToString()) ;
}

//创建控件并将它们放在窗体上。
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;

//如果不是最后一个参数,它将无法正常工作。
checkBox.DataBindings.Add(CheckState,table,MyColumn,true);

按钮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:



为什么起作用 b
$ b

绑定有一个称为FormatObject的私有方法,它负责从数据源获取适合在控件上显示的值的表示。



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



对源代码状态的注释:



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



FormatObjectInternal状态的注释:



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



在FormatObjectInternal内部,它检查数据源为null或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.

这篇关于如何绑定一个CheckBox到bool类型的DbColumn是可空的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆