C# 在WPF控件中将EventHandler声明为静态或非静态
我正在创建一个具有命令行为的自定义控件,遇到了一些奇怪的事情。我发现的一些文章将CanExecuteChangedHandler事件处理程序声明为静态,而其他文章则声明为非静态。Microsoft的SDK文档显示静态,但当我将其声明为静态时,在使用多个控件时会出现奇怪的行为C# 在WPF控件中将EventHandler声明为静态或非静态,c#,wpf,wpf-controls,binding,C#,Wpf,Wpf Controls,Binding,我正在创建一个具有命令行为的自定义控件,遇到了一些奇怪的事情。我发现的一些文章将CanExecuteChangedHandler事件处理程序声明为静态,而其他文章则声明为非静态。Microsoft的SDK文档显示静态,但当我将其声明为静态时,在使用多个控件时会出现奇怪的行为 private static EventHandler canExecuteChangedHandler; private void AddSecureCommand(ISecureCommand secureComman
private static EventHandler canExecuteChangedHandler;
private void AddSecureCommand(ISecureCommand secureCommand)
{
canExecuteChangedHandler = new EventHandler(CanExecuteChanged);
securityTypeChangedHandler = new EventHandler(SecurityTypeChanged);
if (secureCommand != null)
{
secureCommand.CanExecuteChanged += canExecuteChangedHandler;
secureCommand.SecurityTypeChanged += securityTypeChangedHandler;
}
}
有人知道正确的方法吗?我是否做错了导致静态EventHandler无法工作的事情?保留
EventHandler
的本地副本的原因是WPF命令子系统在内部使用弱引用,因此我们需要保留对添加到CanExecuteChanged
事件。如果事实上,任何时候我们添加到任何命令子系统事件中,我们也应该遵守这种做法,就像您对securitypechanged
所做的那样
对您的问题的简短回答是,canExecuteChangedHandler
可以是静态的,但是您必须小心地只初始化它一次。它可以是静态的原因是,如果CanExecuteChanged
是静态的,则所有new EventHandler(CanExecuteChanged)
都将执行相同的操作。初始化它一次的原因是不同的实例是不同的
具有正确只读语义的私有属性是:
static EventHandler canExecuteChangedHandler
{
get
{
if (internalCanExecuteChangedHandler == null)
internalCanExecuteChangedHandler = new EventHandler(CanExecuteChanged);
return internalCanExecuteChangedHandler;
}
}
static EventHandler internalCanExecuteChangedHandler;
但这仅在CanExecuteChanged
为静态时有效。如果不是,则删除静态
限定符。在这两种情况下,您都必须小心地实际使用该属性
在此特定示例中,第二次调用AddSecureCommand
时,第一次调用的canExecuteChangedHandler
有被垃圾收集的风险
最后,如果这一切听起来像是黑魔法,这里有一个代码示例来说明发生了什么
public class Container
{
private WeakReference reference;
public object Object
{
get { return reference.IsAlive ? reference.Target : null; }
set { reference = new WeakReference(value); }
}
}
public class DelegateTest
{
private EventHandler eventHandler;
private Container container1;
private Container container2;
void MyEventHandler(object sender, EventArgs args)
{
}
public DelegateTest()
{
this.eventHandler = new EventHandler(MyEventHandler);
this.container1 = new Container { Object = this.eventHandler };
this.container2 = new Container { Object = new EventHandler(MyEventHandler) };
GC.Collect();
Console.WriteLine("container1: {0}", this.container1.Object == null);
Console.WriteLine("container2: {0}", this.container2.Object == null);
}
}
这将产生以下输出:
container1: False
container2: True
这表示在垃圾收集过程中,第二个容器的
EventHandler
垃圾“从下面”收集。这是通过设计弱引用的工作方式,并解释您需要自己保留对它的引用。我理解垃圾收集的原因,我知道我必须在类级别声明EventHandler。我遇到的问题是,当我多次实例化这个类时,当它是静态的时,我会得到奇怪的行为。我试图编辑上面的评论,但显然我只有5分钟的时间来更新它。要在上面详细说明。。。我遇到的问题是,当我多次实例化类(或控件)时,当它是静态的时,我会得到奇怪的行为。在做了更多的研究之后,我发现EventHandler委托的目标是特定于实例的。在我的例子中,使用静态EventHandler会导致问题。我知道有时可能会使用静态EventHandler,但我猜它在我的情况下不起作用。在将其添加到命令事件后,仍然必须小心不要修改它。我将更新答案。要对垃圾收集进行评论,如果我不将EventHandler创建为静态,那么每个类实例将创建一个实例,这也将阻止垃圾收集。谢谢你提供的所有信息。