简体   繁体   English

WPF绑定失败,并为INotifyPropertyChanged.PropertyChanged自定义添加和删除访问器

[英]WPF binding fails with custom add and remove accessors for INotifyPropertyChanged.PropertyChanged

I have a scenario which is causing strange behavior with WPF data binding and INotifyPropertyChanged . 我有一种情况会导致WPF数据绑定和INotifyPropertyChanged异常行为。 I want a private member of the data binding source to handle the INotifyPropertyChanged.PropertyChanged event. 我希望数据绑定源的私有成员处理INotifyPropertyChanged.PropertyChanged事件。

Here's the source code: 这是源代码:

XAML XAML

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="TestApplication.MainWindow"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    Height="100" Width="100">
    <StackPanel>
        <CheckBox IsChecked="{Binding Path=CheckboxIsChecked}" Content="A" />
        <CheckBox IsChecked="{Binding Path=CheckboxIsChecked}" Content="B" />
    </StackPanel>
</Window>

Normal implementation works 正常执行工作

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public bool CheckboxIsChecked
    {
        get { return this.mCheckboxIsChecked; }
        set
        {
            this.mCheckboxIsChecked = value;
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs("CheckboxIsChecked"));
        }
    }

    private bool mCheckboxIsChecked = false;

    public MainWindow() { InitializeComponent(); }
}

Desired implementation doesn't work 所需的实现无效

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged
    {
        add { lock (this.mHandler) { this.mHandler.PropertyChanged += value; } }
        remove { lock (this.mHandler) { this.mHandler.PropertyChanged -= value; } }
    }

    public bool CheckboxIsChecked
    {
        get { return this.mHandler.CheckboxIsChecked; }
        set { this.mHandler.CheckboxIsChecked = value; }
    }

    private HandlesPropertyChangeEvents mHandler = new HandlesPropertyChangeEvents();

    public MainWindow() { InitializeComponent(); }

    public class HandlesPropertyChangeEvents : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public bool CheckboxIsChecked
        {
            get { return this.mCheckboxIsChecked; }
            set
            {
                this.mCheckboxIsChecked = value;
                PropertyChangedEventHandler handler = this.PropertyChanged;
                if (handler != null)
                    handler(this, new PropertyChangedEventArgs("CheckboxIsChecked"));
            }
        }

        private bool mCheckboxIsChecked = false;
    }
}

That's just a guess, but I think it might be because the sender parameter passed to the event handler is an instance of HandlesPropertyChangeEvents , when the binding expects an instance of MainWindow . 这只是一个猜测,但是我认为可能是因为当绑定需要MainWindow的实例时,传递给事件处理程序的sender参数是HandlesPropertyChangeEvents的实例。

Try to change your code so that the sender is the MainWindow instance : 尝试更改您的代码,使发送方成为MainWindow实例:

private PropertyChangedEventHandler _propertyChanged;
public event PropertyChangedEventHandler PropertyChanged
{
    add { lock (this.mHandler) { this._propertyChanged += value; } }
    remove { lock (this.mHandler) { this._propertyChanged -= value; } }
}


...

public MainWindow()
{
    InitializeComponent();
    mHandler.PropertyChanged += mHandler_PropertyChanged;
}

private void mHandler_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    var handler = _propertyChanged;
    if (handler != null)
        _propertyChanged(this, e);
}

My working solution is almost exactly the same as the "desired implementation" in my question, with the addition of the Sender property. 除了添加了Sender属性之外,我的工作解决方案与我的问题中的“所需实现”几乎完全相同。

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged
    {
        add { lock (this.mHandler) { this.mHandler.PropertyChanged += value; } }
        remove { lock (this.mHandler) { this.mHandler.PropertyChanged -= value; } }
    }

    public bool CheckboxIsChecked
    {
        get { return this.mHandler.CheckboxIsChecked; }
        set { this.mHandler.CheckboxIsChecked = value; }
    }

    private HandlesPropertyChangeEvents mHandler = new HandlesPropertyChangeEvents();

    public MainWindow()
    {
        InitializeComponent();
        this.mHandler.Sender = this;
    }

    public class HandlesPropertyChangeEvents : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public Sender { get; set; }

        public bool CheckboxIsChecked
        {
            get { return this.mCheckboxIsChecked; }
            set
            {
                this.mCheckboxIsChecked = value;
                PropertyChangedEventHandler handler = this.PropertyChanged;
                if (handler != null)
                    handler(this.Sender, new PropertyChangedEventArgs("CheckboxIsChecked"));
            }
        }

        private bool mCheckboxIsChecked = false;
    }
}

This example is a bit artificial, but in my application moving the event handling code outside of the bound class makes sense. 这个例子有些人为,但是在我的应用程序中,将事件处理代码移到绑定类之外是有意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么ObservableCollection会隐藏INotifyPropertyChanged.PropertyChanged - Why does ObservableCollection hide INotifyPropertyChanged.PropertyChanged 通过反射触发INotifyPropertyChanged.PropertyChanged - Fire INotifyPropertyChanged.PropertyChanged via Reflection 创建BindableProprties时,GetValue和SetValue与INotifyPropertyChanged.PropertyChanged? - GetValue and SetValue vs INotifyPropertyChanged.PropertyChanged when creating BindableProprties? 已触发INotifyPropertyChanged.PropertyChanged,但表单加载后UI未更新 - INotifyPropertyChanged.PropertyChanged fired, but UI not updated after form loads WPF文本框未使用数据绑定,iNotifyPropertyChanged和PropertyChanged触发器更新 - WPF TextBox Not Updating with Data Binding, iNotifyPropertyChanged, and PropertyChanged Trigger WPF数据绑定失败(PropertyChanged没有订阅者) - WPF data binding fails (no subscriber for PropertyChanged) WPF双向绑定和PropertyChanged - WPF TwoWay Binding and PropertyChanged WPF 4:PropertyChanged没有更新Binding - WPF 4 : PropertyChanged not updating Binding WPF〜绑定和INotifyPropertyChanged问题 - WPF ~ Trouble with Binding & INotifyPropertyChanged WPF绑定未使用UpdateSourceTrigger = PropertyChanged更新 - WPF Binding not updating with UpdateSourceTrigger=PropertyChanged
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM