C# Winforms中的两种数据绑定方式
我正在学习数据绑定,我有一个具有一个属性的类,然后我有另一个具有combobox和2个值“1和2”的类,我已使用该属性创建了我的类的数组对象,因此当combobox具有1时,我的文本框将给它一个值给类[0]。属性,而如果我有2个,则会发生这种情况类[1].property以下是代码,以便您更好地理解:C# Winforms中的两种数据绑定方式,c#,C#,我正在学习数据绑定,我有一个具有一个属性的类,然后我有另一个具有combobox和2个值“1和2”的类,我已使用该属性创建了我的类的数组对象,因此当combobox具有1时,我的文本框将给它一个值给类[0]。属性,而如果我有2个,则会发生这种情况类[1].property以下是代码,以便您更好地理解: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System
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;
}
}
}
一切正常,但这是一种单向数据绑定。事实上,我必须使用click按钮设置属性,在这种情况下,以下两者之间没有任何区别:
textBox1.DataBindings.Add("Text", prova[a], "pollo", false, DataSourceUpdateMode.OnPropertyChanged);
及
那么为什么要使用数据绑定呢?我的意思是,我怎样才能使它两种方式,以便自动设置我的属性
谢谢您的代码中存在一些问题,导致绑定无法正常工作,从而影响了它的实用性 首先,需要明确的是:正在设置的绑定位于当前选定的
Class1
对象和TextBox
的Text
属性之间。您正在使用组合框
更改要将文本框
绑定到的当前选定对象。我想你知道,但我想确定一下
现在,就代码中的问题而言
Class1
被声明为struct
,而不是class
。struct
类型是一种值类型,这意味着每当代码需要对象引用时,该值的副本都会被装箱(存储在对象的实例中)。理解此装箱值是副本非常重要。它与存储在数组中的值完全断开连接,因此即使绑定成功设置,对对象的更改也不会反映在从数组中检索对象值的代码中的其他地方
Class1
类型未实现属性更改事件。在Winforms中,您可以实现名为polloChanged
(即属性名称,后跟单词Changed
,拼写和大写与之完全相同)的事件,也可以实现INotifyPropertyChanged
接口。如果没有这两种机制,双向数据绑定就无法工作,因为框架无法知道属性的值何时发生了更改。(具有讽刺意味的是,真正起作用的是目标到源的绑定……也就是说,因为TextBox
类实现了TextChanged
事件,所以当目标属性更改时,数据绑定能够设置源属性。但它不会走另一条路)Class1
(作为实际的class
,并带有必要的polloChanged
事件),正确地配置了绑定,并将对象的pollo
属性绑定到标签
,以便明确对象的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;
}
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);
}
}
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;
}