相关:https://stackoverflow.com/a/17451872/3485263
我有一个实现INotifyPropertyCHanged
的类。存在System.Windows.Forms.Binding
的多个实例,这些实例将其属性绑定到Windows Forms应用程序中某些控件的属性。
public class Device : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string property_name)
{
if (PropertyChanged != null) // if there are any subscribers
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property_name));
}
public bool connected {get; set;}
...
绑定在表单类中发生如下:
button_Reboot.DataBindings.Add("Enabled", _device, "connected", false,
DataSourceUpdateMode.Never);
此代码的问题是OnPropertyChanged
处理程序和表单代码似乎在不同的线程中工作。这是因为_device
订阅了封装的SerialPort
实例的事件,并在串行端口引发的事件上更新了它的属性,这似乎是在另一个线程中发生的。因此,我得到InvalidOperationException
的说法是,控件是从不是在其上创建的线程的线程访问的。
我根据this answer更改了代码。该答案的评论也包含对我问题的描述。
void OnPropertyChanged(string property_name)
{
var handler = PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(property_name);
foreach (PropertyChangedEventHandler h in handler.GetInvocationList())
{
var synch = h.Target as ISynchronizeInvoke;
if (synch != null && synch.InvokeRequired)
synch.Invoke(h, new object[] { this, e });
else
h(this, e);
}
}
}
该答案的作者期望h.Target
是Control
,但在我的情况下却是System.ComponentModel.ReflectPropertyDescriptor
,这是我在调试期间观察到的某些运行时类型。该类型未实现ISynchronizeInvoke
,这导致synch
为null
,无论如何都会引发异常,因为控制方法只是直接调用而不是同步调用。 >
我的问题是我是否可以使我的OnPropertyChanged
处理程序使用控件的PropertyChangedEventHandler
界面访问控件的ISynchronizeInvoker
。我以.NET 4.6.2为目标,并且正在使用Visual Studio 2013。