如何将 CheckBox 绑定到可为空的布尔类型 DbColumn? [英] How to bind a CheckBox to a bool typed DbColumn that is nullable?

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

问题描述

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

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.

  • 我尝试通过设计器将 Checked 属性绑定到该列:只有当该列的默认值设置为 True错误.
  • 我尝试通过设计器将 CheckState 属性绑定到列,并附加我自己的 FormatParse 事件处理程序,但它们永远不会被调用:

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

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

  • 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);
    

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

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

    推荐答案

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

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

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

    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:

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

    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.

    我可能是 Parse、Format 或 Binding 妨碍了你,也可能是 Windows 窗体在 2008 年的行为与 2005 年不同

    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

    8 月 18 日更新:它也可以通过设计器和代码在 Visual Studio 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--;
            }
        }
    }
    
    

    <小时>

    8 月 23 日更新:

    为什么会起作用

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

    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.

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

    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.

    源码状态注释:

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

    "The real conversion work happens inside FormatObjectInternal()"

    FormatObjectInternal 状态的注释:

    The comments for FormatObjectInternal state:

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

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

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

    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.

    如您所见,这种情况非常常见,令人惊讶的是它在 Windows Forms 1.x 上不起作用.幸运的是,它已在 2.0 及更高版本上修复.

    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 绑定到可为空的布尔类型 DbColumn?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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