代码之家  ›  专栏  ›  技术社区  ›  Mac

如何将复选框绑定到可为空的bool类型的dbcolumn?

  •  4
  • Mac  · 技术社区  · 15 年前

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

    • 我试着把 Checked 通过设计器将属性设置为列:只有当列的默认值设置为 True False .
    • 我试着把 CheckState 通过设计器将属性附加到列,并附加自己的 Format 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 在代码中,附加我的事件处理程序并将其添加到 复选框 绑定:事件处理程序仍然不会被调用…

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

    作为注释:A 否为空 只有当来自 数据集 (表示从未设置过值)。但是用户应该只能将值设置为 通过 复选框 .

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

    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;
    }
    
    2 回复  |  直到 15 年前
        1
  •  7
  •   Alfred Myers    15 年前

    您是否尝试将checkbox.checkstate绑定到DataColumn而不附加到Parse和Format事件,或者不处理绑定?

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

    注意:只有当dbnull值来自数据集时才可接受(这意味着从未设置过该值)。但是用户应该只能通过复选框将值设置为true或false。

    我可能是以您的方式进行解析、格式化或绑定,或者Windows窗体在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 &lt 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日更新:

    为什么工作

    绑定有一个名为FormatObject的私有方法,该方法负责获取来自适合在控件上显示的数据源的值的表示形式。

    启用格式设置后,binding.formatObject()将运行一个代码路径,该路径将调用binding.format事件的最终处理程序。如果任何处理程序更改了通过convertEventArgs.value从数据源传播到控件的值,则将使用该值。否则,它将在名为System.Windows.Forms.Formatter的内部类上调用名为FormatObject的默认格式化程序。

    源代码状态的注释:

    _真正的转换工作发生在formatObjectInternal()__

    格式化对象内部状态的注释:

    _156;执行一些特殊情况转换(例如Boolean到CheckState)__

    在FormatObjectinal内部,它检查来自数据源的值是空值还是dbnull,如果是这种情况,它检查要绑定的属性的类型是否为checkState。如果是这种情况,它将返回checkstate.indetermate。

    如您所见,这是一个很常见的情况,它在WindowsForm1.x上不起作用,这是一个惊喜。幸运的是,它在2.0及更高版本上修复了它。

        2
  •  1
  •   TcKs    15 年前

    我知道,easist方法是从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;
                }
            }
        }
    }