[英]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: 这是源代码:
<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>
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(); }
}
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.