سؤال

What is the best way of accomplishing this?

Some sample code:

Adding the binding to the text boxes, and adding the event listener:

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;

The PropertyChangedEventHandler handler is passed in from a parent user control, as a new PropertyChangedEventHandler(HandlePropertyChange). This is just because parent contains the Save button that is enabled/disabled, and a tab control that has multiple pages containing multiple user controls. It would eventually want to handle property changes for all the children, so seemed to be the best way of structuring things (??)

This is the object/property to bind to (based on this 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;
    }
}

I know there is a parameter called formattingEnabled on the Binding object, but this looks like it is to do with date/time/currency formatting.

I can't see any way of getting back to the textbox from the PropertyChangedEvent, as it is just referring back to the property itself.

I saw this: Binding a bool property to BackColor Property of a WinForm - but I'm not sure if adding extra properties is the best approach?

UPDATE

Based on Bond's answer, I could do this:

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

So passing in the entire ControlCollection on the User Control into the event hander.

And then have the event handler do this:

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;
}

But it seems unwieldy, and if the form changed (e.g. putting some textboxes into a groupbox, or wanting to do the same to other control types) it would no longer work.

I guess on the User Control side, I would know which controls I want to bind to, so I could just create a collection of those and pass those in as the sender object, but it is still not particularly nice as I'd have to maintain that list separately...

Any thoughts?

هل كانت مفيدة؟

المحلول

you can do this

this.MyObject.PropertyChanged += (s, e) => handler(myTextBox, e);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top