[英]Winforms Textbox with two way DataBinding not working as it should be
[英]Two Ways DataBinding in Winforms
我正在学习数据绑定,我有一个带有一个属性的类,然后我有另一个带有组合框和2个值“1和2”的类,我创建了一个带有属性的类的数组对象,所以当组合框有1我的文本框会给它一个类[0] .property的值,相反,如果我有2这个发生在类[1] .property这里是代码,所以你会更好地理解:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
struct Class1
{
public string pollo { get; set; }
}
}
我的第二堂课:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
Class1[] prova = new Class1[2];
int a;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
a = Convert.ToInt32(comboBox1.SelectedItem) - 1;
prova[a].pollo = textBox1.Text;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
a = Convert.ToInt32(comboBox1.SelectedItem) - 1;
textBox1.DataBindings.Add("Text", prova[a], "pollo", false, DataSourceUpdateMode.OnPropertyChanged);
textBox1.DataBindings.Clear();
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.SelectedIndex = 0;
}
}
}
一切正常,但这是一种单向数据绑定实际上我必须使用单击按钮设置属性,在这种情况下,没有这样的区别:
textBox1.DataBindings.Add("Text", prova[a], "pollo", false, DataSourceUpdateMode.OnPropertyChanged);
和
textBox1 = prova[a];
那么为什么要使用数据绑定? 我的意思是我怎么能用两种方式来自动设置我的属性?
谢谢
您的代码中存在一些问题,导致绑定无法正常工作,从而模糊了实用性。
首先,要明确:正在设置的绑定位于当前选定的Class1
对象和TextBox
的Text
属性之间。 您正在使用ComboBox
更改当前选定的对象以将TextBox
绑定到。 我假设你已经意识到这一点,但我想确定一下。
现在,就代码中的问题而言......
最严重的问题是您的数据类型Class1
被声明为struct
而不是class
。 struct
类型是值类型 ,意味着只要代码需要对象引用,就会将值的副本装箱 (存储在object
的实例中)。 理解这个盒装值是一个副本是非常重要的。 它与您存储在数组中的值完全断开,因此即使成功设置了绑定,对象的更改也不会反映在从数组中检索对象值的代码中的其他位置。
几乎同样严重的是你在设置后立即清除绑定 。 这完全否定了数据绑定的要点,即允许框架根据另一个对象的更改自动更新属性值。 所以是的,在你的代码示例中,set-binding-then-clear-binding操作与简单地直接设置属性之间几乎没有任何区别 。
这两个问题中的任何一个都足以阻止数据绑定以有用的方式工作。 但还有第三个问题......
Class1
类型未实现属性更改事件。 在Winforms中,您可以实现名为polloChanged
的事件(即属性名称,后跟单词Changed
,拼写和大写完全相同),或者实现INotifyPropertyChanged
接口。 如果没有这些机制,双向数据绑定就无法工作,因为框架无法知道属性值何时发生了变化。 (讽刺的是,什么是工作目标到源绑定...这是,因为TextBox
类实现了TextChanged
事件,数据绑定能够设置源属性当目标属性更改,但它不走另一种方法)。 下面是一个代码版本,它充分利用数据绑定,正确实现Class1
(作为实际class
,并使用必要的polloChanged
事件),正确配置绑定,并将对象的pollo
属性绑定到Label
以便它清楚对象的pollo
属性正在更新:
class Class1
{
private string _pollo = "";
public string pollo
{
get { return _pollo; }
set
{
_pollo = value;
Raise(polloChanged, this);
}
}
private static void Raise(EventHandler handler, object sender)
{
if (handler != null)
{
handler(sender, EventArgs.Empty);
}
}
public event EventHandler polloChanged;
}
public partial class Form1 : Form
{
private Class1[] _prova =
{
new Class1 { pollo = "<not set 1>" },
new Class1 { pollo = "<not set 2>" }
};
public Form1()
{
InitializeComponent();
comboBox1.SelectedIndex = 0;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// Obviously in a more complicated data binding scenario, you might
// want to be more specific about which binding(s) is(are) being
// removed, rather than just clearing everything.
textBox1.DataBindings.Clear();
label1.DataBindings.Clear();
// If the user edits the text in the TextBox, the pollo property
// of the currently-selected object will be immediately updated
textBox1.DataBindings.Add("Text", _prova[comboBox1.SelectedIndex],
"pollo", false, DataSourceUpdateMode.OnPropertyChanged);
// We're never going to change the label1.Text property directly,
// so the binding doesn't ever need to update the source property.
label1.DataBindings.Add("Text", _prova[comboBox1.SelectedIndex],
"pollo", false, DataSourceUpdateMode.Never);
}
}
我假设您可以在表单中推断出必要的textBox1
, comboBox1
和label1
控件,而不是让我发布所有Designer代码。
最后,如果你更喜欢INotifyPropertyChanged
方法,这就是你的Class1
使用这种技术的样子:
class Class1 : INotifyPropertyChanged
{
private string _pollo = "";
public string pollo
{
get { return _pollo; }
set
{
_pollo = value;
OnPropertyChanged();
}
}
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.