.NET WinForms INotifyPropertyChanged updates all bindings when one is changed. Better way?

后端 未结 2 529
清酒与你
清酒与你 2020-12-25 12:44

In a windows forms application, a property change that triggers INotifyPropertyChanged, will result in the form reading EVERY property from my bound object, not just the pro

相关标签:
2条回答
  • 2020-12-25 13:07

    The reason why all properties are being read when the event gets fired rests in the PushData method called on the binding object when the ProperyChanged event is fired. If you look at the stacktrace, you will notice that the PropValueChanged method of the internal object BindToObject is called, that in turn calls the Oncurrentchanged event on the BindingManager. The binding mechanism keeps track of the current item changes, but it doesn't do a more granular distinction. The "culprit" PushData method calls the getter on your properties (take a look at the code using reflector). So there is no way around it. That being said, as a rule of thumb, in the get and set accessors it is not recommended to do heavy processing, use separate get and set methods for that (if possible)

    Also take a look at this article, and this comment in particular (http://www.codeproject.com/Messages/2514032/How-Binding-watches-control-properties-i-e-how-doe.aspx), that explains exactly how the propertychanged event gets fired, though it will not address your getter problem: http://www.codeproject.com/KB/database/databinding_tutorial.aspx?msg=2514032

    An idea to explore is to delay the getter being called. You can achieve this by playing around with the ControlUpdateMode property of the binding. When this value is set to Never, the corresponding control will not update when there is a change. However, when you switch the value back to OnPropertyChanged, PushData method will be called, so the getters will be accessed. So considering your example this code will temporary prevent the textbox 2 to update:

    void but_Click(object sender, EventArgs e)
            {                   
                txt2.DataBindings[0].ControlUpdateMode = ControlUpdateMode.Never;
                _presenter.SomeText1 = "some text 1";
            }
    
    0 讨论(0)
  • 2020-12-25 13:11

    I'm testing subclassing binding like this and managing OnPropertyChanged, maybe helps you.

    public class apBinding : Binding
    {
    
            public apBinding(string propertyName, INotifyPropertyChanged dataSource, string dataMember)
                : base(propertyName, dataSource, dataMember)
            {
                this.ControlUpdateMode = ControlUpdateMode.Never;
                dataSource.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChanged);
            }
    
            private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
    
                if (e.PropertyName == this.BindingMemberInfo.BindingField)
                {
                     this.ReadValue();
                }
            }
        }
    

    Now the problem that i find is that the control overwrites the value of the linked object, so i modified to

    public class apBinding : Binding
    {
    
            public apBinding(string propertyName, INotifyPropertyChanged dataSource, string dataMember)
                : base(propertyName, dataSource, dataMember)
            {
    
                dataSource.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChanged);
            }
    
            private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                this.ControlUpdateMode = ControlUpdateMode.Never;
                if (e.PropertyName == this.BindingMemberInfo.BindingField)
                {
                     this.ReadValue();
                }
            }
        }
    

    then the first time propertychanges is called i disable controlupdate. and the control is correctly updated at the first run.

    0 讨论(0)
提交回复
热议问题