【问题标题】:Change backcolor of textboxes when their bound properties change?绑定属性更改时更改文本框的背景颜色?
【发布时间】:2014-02-06 08:48:53
【问题描述】:

实现这一目标的最佳方法是什么?

一些示例代码:

为文本框添加绑定,并添加事件监听器:

this.MyObject = new MyObject();

this.myTextBox.DataBindings.Add(
    new Binding("Text", this.MyObject, "MyProperty", true,
        DataSourceUpdateMode.OnPropertyChanged));

this.myOtherTextBox.DataBindings.Add(
    new Binding("Text", this.MyObject, "MyOtherProperty", true,
        DataSourceUpdateMode.OnPropertyChanged));

this.MyObject.PropertyChanged += handler;

PropertyChangedEventHandler handler 是从父用户控件传入的 new PropertyChangedEventHandler(HandlePropertyChange)。这只是因为 parent 包含启用/禁用的 Save 按钮,以及一个包含多个用户控件的多个页面的选项卡控件。它最终会想要处理所有孩子的属性更改,因此似乎是构建事物的最佳方式(??)

这是要绑定的对象/属性(基于此https://stackoverflow.com/a/1316566/1061602

public class MyObject : INotifyPropertyChanged
{
    private int myProperty;
    public int MyProperty
    {
      get { return myProperty; }
      set { SetField(ref myProperty, value, () => MyProperty); }
    }

    private int myOtherProperty;
    public int MyOtherProperty
    {
      get { return myOtherProperty; }
      set { SetField(ref myOtherProperty, value, () => MyOtherProperty); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
    {
      if (selectorExpression == null) throw new ArgumentNullException("selectorExpression");
      var body = selectorExpression.Body as MemberExpression;
      if (body == null) throw new ArgumentException("The body must be a member expression");
      OnPropertyChanged(body.Member.Name);
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetField<T>(ref T field, T value, Expression<Func<T>> selectorExpression)
    {
      if (EqualityComparer<T>.Default.Equals(field, value)) return false;

      field = value;
      OnPropertyChanged(selectorExpression);
      return true;
    }
}

我知道Binding 对象上有一个名为formattingEnabled 的参数,但这看起来与日期/时间/货币格式有关。

我看不到任何从 PropertyChangedEvent 返回文本框的方法,因为它只是指回属性本身。

我看到了这个:Binding a bool property to BackColor Property of a WinForm - 但我不确定添加额外的属性是否是最好的方法?

更新

根据邦德的回答,我可以这样做:

this.MyObject.PropertyChanged += (s, e) => handler(this.Controls, e);

因此将用户控件上的整个 ControlCollection 传递到事件处理程序中。

然后让事件处理程序执行此操作:

public void ConfigChanged(object sender, EventArgs e)
{
  if (sender is ControlCollection)
  {
    var allControls = (ControlCollection)sender;
    foreach (var control in allControls)
    {
      if (control is TextBox)
      {
        var textBox = (TextBox)control;
        if (textBox.DataBindings[0].BindingMemberInfo.BindingField == 
            (e as PropertyChangedEventArgs).PropertyName)
        {
          textBox.BackColor = Color.LightGoldenrodYellow;
        }
      }
    }
  }
  this.saveButton.Enabled = true;
}

但它看起来很笨拙,如果表单发生变化(例如,将一些文本框放入组框,或者想对其他控件类型做同样的事情),它将不再起作用。

我想在用户控件方面,我会知道我想绑定哪些控件,所以我可以创建一个集合并将它们作为 sender 对象传递,但它仍然不是特别好,因为我必须单独维护该列表...

有什么想法吗?

【问题讨论】:

  • HandlePropertyChange 看起来是在表单的类中定义的 - 您可以直接从那里访问文本框
  • 谢谢,我刚刚意识到示例代码有点过于简化了。不过好喊。你怎么看?

标签: c# winforms textbox inotifypropertychanged backcolor


【解决方案1】:

你可以这样做

this.MyObject.PropertyChanged += (s, e) => handler(myTextBox, e);

【讨论】:

  • 这很好用,你将如何为共享相同属性更改事件的多个文本框缩放它?为每个属性添加单独的 PropertyChangedEventHandler?
  • foreach(var tb in textBoxes){ this.MyObject.PropertyChanged += (s, e) => handler(tb, e);}// 即 - 只订阅此事件的所有文本框.
  • 这会一次性改变所有的文本框吗?好像一个属性发生了变化,它会触发一个单独的事件来格式化每个属性?
  • 如果一个属性发生变化,它将为每个文本框执行你的“处理程序”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 2013-01-15
  • 2013-05-20
  • 2012-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多