Mac*_*Mac 4 .net data-binding checkbox dataset winforms
在Windows窗体(.NET 2.0,Visual Studio 2005 SP1)中:我有一个类型DataSet为type的列System.Boolean,可以为空,默认值为DBNull.我有一个Form,包含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
};
Run Code Online (Sandbox Code Playgroud)我试图Binding在代码中创建一个自定义实例,附加我的事件处理程序并将其添加到CheckBox绑定:事件处理程序仍然永远不会被调用...
Binding b=new Binding("CheckState", _BindingSource, "MyColumn", false, DataSourceUpdateMode.OnPropertyChanged, DBNull.Value);
Run Code Online (Sandbox Code Playgroud)作为注释:DBNull只有当来自DataSet(这意味着从未设置过值)时,值才可接受.但是用户应该只能将值设置为True或False通过CheckBox.
作为参考,这里是解析和格式化方法的代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
您是否尝试将CheckBox.CheckState绑定到DataColumn而不附加Parse和Format事件或搞乱绑定?
不幸的是我没有可用的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--;
}
}
}
Run Code Online (Sandbox Code Playgroud)
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及更高版本.