我正在学习数据绑定,我有一个带有一个属性的类,然后我有另一个带有组合框和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; }
}
}
Run Code Online (Sandbox Code Playgroud)
我的第二堂课:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
一切正常,但这是一种单向数据绑定实际上我必须使用单击按钮设置属性,在这种情况下,没有这样的区别:
textBox1.DataBindings.Add("Text", prova[a], "pollo", false, DataSourceUpdateMode.OnPropertyChanged);
Run Code Online (Sandbox Code Playgroud)
和
textBox1 = prova[a];
Run Code Online (Sandbox Code Playgroud)
那么为什么要使用数据绑定?我的意思是我怎么能用两种方式来自动设置我的属性?
谢谢
您的代码中存在一些问题,导致绑定无法正常工作,从而模糊了实用性.
首先,要明确:正在设置的绑定是在当前选定的Class1
对象和Text
属性之间TextBox
.您正在使用ComboBox
更改当前所选对象来绑定TextBox
到.我假设你已经意识到这一点,但我想确定一下.
现在,就代码中的问题而言......
最严重的问题是您的数据类型Class1
被声明为a struct
而不是a 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;
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
我假设您可以在表单中推断出必要的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;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6315 次 |
最近记录: |