在继承中复制 EventHandler class
Copy EventHandler in inherited class
我正在用 c# WPF 开发应用程序。
我使用 class PropertyChangedNotifier
来管理 INotifyPropertyChanged(参见 )。
我使用 classical ViewModelBase :
public class ViewModelBase : INotifyPropertyChanged, IRequestClose
{
public PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = _propertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
在我的 MainViewModel : ViewModelBase
中,我有一个像这样工作的 PropertyChangedNotifier<MainViewModel>
:
class MainViewModel : ViewModelBase
{
private PropertyChangedNotifier<MainViewModel> _notifier;
public new event PropertyChangedEventHandler PropertyChanged
{
add { _notifier.PropertyChanged += value; }
remove { _notifier.PropertyChanged -= value; }
}
public MainViewModel()
{
_notifier = new PropertyChangedNotifier<MainViewModel>(this);
}
protected new void OnPropertyChanged(string propertyName)
{
_notifier.OnPropertyChanged(propertyName);
}
}
但未检测到更改,当值更改时,我的 MainWindows 不会刷新(不使用 PropertyChangedNotifier 它会起作用)。我看到系统通过使用 WindowsBase.dll!System.ComponentModel.PropertyChangedEventManager.StartListening(object source)
启动 windows 然后我看到当调用 MainViewModel 的构造函数时我的 ViewModelBase.PropertyChanged 不为空。
是否可以制作这样的东西:
public MainViewModel()
{
_notifier = new PropertyChangedNotifier<MainViewModel>(this);
_notifier.PropertyChanged = base.PropertyChanged;
}
这会修复我的错误吗?
编辑:
来自 link 的 PropertyChangeNotifier:
[AttributeUsage( AttributeTargets.Property )]
public class DepondsOnAttribute : Attribute
{
public DepondsOnAttribute( string name )
{
Name = name;
}
public string Name { get; }
}
public class PropertyChangedNotifier<T> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public PropertyChangedNotifier( T owner )
{
mOwner = owner;
}
public void OnPropertyChanged( string propertyName )
{
var handler = PropertyChanged;
if( handler != null ) handler( mOwner, new PropertyChangedEventArgs( propertyName ) );
List<string> dependents;
if( smPropertyDependencies.TryGetValue( propertyName, out dependents ) )
{
foreach( var dependent in dependents ) OnPropertyChanged( dependent );
}
}
static PropertyChangedNotifier()
{
foreach( var property in typeof( T ).GetProperties() )
{
var dependsOn = property.GetCustomAttributes( true )
.OfType<DepondsOnAttribute>()
.Select( attribute => attribute.Name );
foreach( var dependency in dependsOn )
{
List<string> list;
if( !smPropertyDependencies.TryGetValue( dependency, out list ) )
{
list = new List<string>();
smPropertyDependencies.Add( dependency, list );
}
if (property.Name == dependency)
throw new ApplicationException(String.Format("Property {0} of {1} cannot depends of itself", dependency, typeof(T).ToString()));
list.Add( property.Name );
}
}
}
private static readonly Dictionary<string, List<string>> smPropertyDependencies = new Dictionary<string, List<string>>();
private readonly T mOwner;
}
问题是当创建我的 MainViewModel
时,base.PropertyChanged
为空。构造函数被调用,fields/properties 初始化(有些调用 OnPropertyChanged)并在 MainView.InitializeComponent() 之后在 base.PropertyChanged
中添加一个处理程序(我附加了一个调试器来查看)。此添加在 ViewModelBase
中完成,忽略 MainViewModel
中的 public new event PropertyChangedEventHandler PropertyChanged
。
我想看看base.PropertyChanged
有没有被修改复制过来
我已经这样做了,不知道有没有好的idea,大家觉得呢?
public class ViewModelBase : INotifyPropertyChanged, IRequestClose
{
protected event PropertyChangedEventHandler _propertyChanged;
protected bool propertyAdded { get; private set; }
public event PropertyChangedEventHandler PropertyChanged
{
add
{
_propertyChanged += value;
propertyAdded = true;
}
remove { _propertyChanged -= value; }
}
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = _propertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public Delegate[] Get_PropertyChanged()
{
isPropertyAdded = false;
Delegate[] delegates = new Delegate[0];
if (_propertyChanged != null)
{
delegates = _propertyChanged.GetInvocationList();
_propertyChanged = null;
}
return delegates;
}
}
和
class MainViewModel : ViewModelBase
{
private PropertyChangedNotifier<MainViewModel> _notifier;
public new event PropertyChangedEventHandler PropertyChanged
{
add { _notifier.PropertyChanged += value; }
remove { _notifier.PropertyChanged -= value; }
}
public MainViewModel()
{
_notifier = new PropertyChangedNotifier<MainViewModel>(this);
}
protected new void OnPropertyChanged(string propertyName)
{
if (isPropertyAdded)
{
foreach (Delegate d in Get_PropertyChanged())
{
_notifier.PropertyChanged += (PropertyChangedEventHandler)d;
}
}
_notifier.OnPropertyChanged(propertyName);
}
}
似乎是对简单 NotifyPropertyChanged("dependentProperty")
的复杂解决方案,尽管我确实理解设计奇特解决方案的愿望。如果它有一些 performance/loc 好处,那将是有道理的,但事实并非如此。它只会增加复杂性。
我正在用 c# WPF 开发应用程序。
我使用 class PropertyChangedNotifier
来管理 INotifyPropertyChanged(参见
我使用 classical ViewModelBase :
public class ViewModelBase : INotifyPropertyChanged, IRequestClose
{
public PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = _propertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
在我的 MainViewModel : ViewModelBase
中,我有一个像这样工作的 PropertyChangedNotifier<MainViewModel>
:
class MainViewModel : ViewModelBase
{
private PropertyChangedNotifier<MainViewModel> _notifier;
public new event PropertyChangedEventHandler PropertyChanged
{
add { _notifier.PropertyChanged += value; }
remove { _notifier.PropertyChanged -= value; }
}
public MainViewModel()
{
_notifier = new PropertyChangedNotifier<MainViewModel>(this);
}
protected new void OnPropertyChanged(string propertyName)
{
_notifier.OnPropertyChanged(propertyName);
}
}
但未检测到更改,当值更改时,我的 MainWindows 不会刷新(不使用 PropertyChangedNotifier 它会起作用)。我看到系统通过使用 WindowsBase.dll!System.ComponentModel.PropertyChangedEventManager.StartListening(object source)
启动 windows 然后我看到当调用 MainViewModel 的构造函数时我的 ViewModelBase.PropertyChanged 不为空。
是否可以制作这样的东西:
public MainViewModel()
{
_notifier = new PropertyChangedNotifier<MainViewModel>(this);
_notifier.PropertyChanged = base.PropertyChanged;
}
这会修复我的错误吗?
编辑:
来自 link 的 PropertyChangeNotifier:
[AttributeUsage( AttributeTargets.Property )]
public class DepondsOnAttribute : Attribute
{
public DepondsOnAttribute( string name )
{
Name = name;
}
public string Name { get; }
}
public class PropertyChangedNotifier<T> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public PropertyChangedNotifier( T owner )
{
mOwner = owner;
}
public void OnPropertyChanged( string propertyName )
{
var handler = PropertyChanged;
if( handler != null ) handler( mOwner, new PropertyChangedEventArgs( propertyName ) );
List<string> dependents;
if( smPropertyDependencies.TryGetValue( propertyName, out dependents ) )
{
foreach( var dependent in dependents ) OnPropertyChanged( dependent );
}
}
static PropertyChangedNotifier()
{
foreach( var property in typeof( T ).GetProperties() )
{
var dependsOn = property.GetCustomAttributes( true )
.OfType<DepondsOnAttribute>()
.Select( attribute => attribute.Name );
foreach( var dependency in dependsOn )
{
List<string> list;
if( !smPropertyDependencies.TryGetValue( dependency, out list ) )
{
list = new List<string>();
smPropertyDependencies.Add( dependency, list );
}
if (property.Name == dependency)
throw new ApplicationException(String.Format("Property {0} of {1} cannot depends of itself", dependency, typeof(T).ToString()));
list.Add( property.Name );
}
}
}
private static readonly Dictionary<string, List<string>> smPropertyDependencies = new Dictionary<string, List<string>>();
private readonly T mOwner;
}
问题是当创建我的 MainViewModel
时,base.PropertyChanged
为空。构造函数被调用,fields/properties 初始化(有些调用 OnPropertyChanged)并在 MainView.InitializeComponent() 之后在 base.PropertyChanged
中添加一个处理程序(我附加了一个调试器来查看)。此添加在 ViewModelBase
中完成,忽略 MainViewModel
中的 public new event PropertyChangedEventHandler PropertyChanged
。
我想看看base.PropertyChanged
有没有被修改复制过来
我已经这样做了,不知道有没有好的idea,大家觉得呢?
public class ViewModelBase : INotifyPropertyChanged, IRequestClose
{
protected event PropertyChangedEventHandler _propertyChanged;
protected bool propertyAdded { get; private set; }
public event PropertyChangedEventHandler PropertyChanged
{
add
{
_propertyChanged += value;
propertyAdded = true;
}
remove { _propertyChanged -= value; }
}
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = _propertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public Delegate[] Get_PropertyChanged()
{
isPropertyAdded = false;
Delegate[] delegates = new Delegate[0];
if (_propertyChanged != null)
{
delegates = _propertyChanged.GetInvocationList();
_propertyChanged = null;
}
return delegates;
}
}
和
class MainViewModel : ViewModelBase
{
private PropertyChangedNotifier<MainViewModel> _notifier;
public new event PropertyChangedEventHandler PropertyChanged
{
add { _notifier.PropertyChanged += value; }
remove { _notifier.PropertyChanged -= value; }
}
public MainViewModel()
{
_notifier = new PropertyChangedNotifier<MainViewModel>(this);
}
protected new void OnPropertyChanged(string propertyName)
{
if (isPropertyAdded)
{
foreach (Delegate d in Get_PropertyChanged())
{
_notifier.PropertyChanged += (PropertyChangedEventHandler)d;
}
}
_notifier.OnPropertyChanged(propertyName);
}
}
似乎是对简单 NotifyPropertyChanged("dependentProperty")
的复杂解决方案,尽管我确实理解设计奇特解决方案的愿望。如果它有一些 performance/loc 好处,那将是有道理的,但事实并非如此。它只会增加复杂性。