【问题标题】:Bind a label to a "variable"将标签绑定到“变量”
【发布时间】:2011-03-09 23:45:27
【问题描述】:

假设我有一个名为 X 的全局变量 INT。由于 X 是全局变量,我们可以假设任何东西都可以修改它的值,因此它每次都会被更改。

假设我有一个名为“label”的 Label 控件。这是我想要完成的:

我想将 label.Text 的值“绑定”到变量 X。这样当变量 X 改变时,它会反射回 label.Text。

现在,我不想编写事件侦听器并与委托一起玩这个(我希望尽可能少的代码)。有没有办法为此使用 DataBinding 组件?或其他任何新技术?

【问题讨论】:

  • 当您指的是全局变量时,您是指类中的静态变量/属性之类的东西吗?
  • @Gishu:是的。像 public int X
  • 请注意,这称为“类实例变量”。

标签: c# winforms data-binding


【解决方案1】:

如果您想使用数据绑定基础架构并反映对值所做的更改,您需要一种方法来通知 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"));
}

【讨论】:

  • 我认为这个答案正是伊恩所需要的。也许在检查 null 之前创建 PropertyChanged 的​​副本会更好,否则它可能会在被调用之前更改为 null,如下所示: protected virtual void OnPropertyChanged(string property) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(property)); } } (详见stackoverflow.com/questions/672638/…
  • 我同意,这是 PropertyChanged 模式的更好参考实现,支持多线程场景。
【解决方案2】:

对于多线程程序(几乎每个 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;
     }
}

【讨论】:

  • 谢谢!在我看来,这是最简单也是最好的解决方案。
【解决方案3】:

我认为您无法绑定到公共变量。变量本身无法通知侦听器其值发生变化。

这就是为什么您需要将变量包装在属性中的原因。在 setter 中,您引发一个事件来通知绑定到它的 UI 控件,以便它们可以刷新并显示新值。该框架为此提供了一种机制 - INotifyPropertyChanged - 试试this link for a how-to

【讨论】:

    【解决方案4】:

    为 X 创建一个属性。在 setter 中更新 label.Text 属性。

    private int _x;
    public int X {
        get 
        { 
            return _x; 
        } 
        set 
        { 
            _x = value;
            label.Text = _x.ToString();
        }
    }
    

    【讨论】:

    • 错了,如果你从不是 UI 线程的线程中执行此操作,你将触发跨线程操作无效异常
    猜你喜欢
    • 2014-07-06
    • 2012-01-12
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2015-06-30
    • 1970-01-01
    • 2020-02-23
    • 1970-01-01
    相关资源
    最近更新 更多