假设我有一个名为X的全局变量INT。由于X是全局的,我们可以假设任何东西都可以修改它的值,因此每次都会更改它。
假设我有一个名为“label”的Label控件。这就是我想要完成的事情:
我想将label.Text的值“绑定”到变量X.这样一来,当变量X被更改时,它将被反射回label.Text。
现在,我不想编写事件监听器并与代理一起玩这个(我希望尽可能少的代码)。有没有办法使用DataBinding组件?或任何其他新技术?
答案 0 :(得分:30)
如果要使用数据绑定基础结构并反映对值所做的更改,则需要一种方法来通知UI有关对绑定值所做的更改。
所以最好的方法是使用属性并实现INotifyPropertyChanged
接口,如下所示:
class frmFoo : Form, INotifyPropertyChanged
{
private string _foo;
public string Foo
{
get { return _foo; }
set
{
_foo = value;
OnPropertyChanged("Foo");
}
}
protected virtual void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
还要记住,您需要先在标签上设置绑定:
public frmFoo()
{
InitializeComponent();
lblTest.DataBindings.Add(new Binding("Text", this, "Foo"));
}
答案 1 :(得分:8)
对于多线程程序(所以几乎每个windows窗体程序)iCe的答案都不是很好,因为它不会让你改变标签(你会得到一些交叉线程错误)。解决问题的最简单方法是在setter中创建属性:
private string _labelText;
public string labelText
{
get { return _labelText; }
set
{
_labelText = value;
updateLabelText(_labelText); //setting label to value
}
}
其中updateLabelText(string)是线程安全的:
delegate void updateLabelTextDelegate(string newText);
private void updateLabelText(string newText)
{
if (label1.InvokeRequired)
{
// this is worker thread
updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText);
label1.Invoke(del, new object[] { newText });
}
else
{
// this is UI thread
label1.Text = newText;
}
}
答案 2 :(得分:3)
我认为你无法绑定到公共变量。变量本身无法通知侦听器其值的变化。
这就是你需要将变量包装在属性中的原因。在setter中,您引发一个事件以通知绑定到它的UI控件,以便它们可以刷新并显示新值。该框架有一个机制 - INotifyPropertyChanged - 尝试this link for a how-to。
答案 3 :(得分:1)
为X创建一个属性。在setter中更新label.Text属性。
private int _x;
public int X {
get
{
return _x;
}
set
{
_x = value;
label.Text = _x.ToString();
}
}