1

(背景:我正在分阶段将 WinForms 应用程序移植到 WPF。目前,我仍然有一个 WinForms 主窗体,其中包含一个包含 WPF 内容的 ElementHost。)

我希望在某些ApplicationCommand(例如CutCopyPaste )更改其 .CanExecute 的值时告知我的应用程序。我认为订阅像 ApplicationCommands.Cut.CanExecuteChanged 这样的全局事件很简单,但我注意到一些奇怪的行为,它似乎并没有被一致地调用。

例如,我创建了一个简化的 WinForms 测试应用程序,它只有一个 ElementHost。然后我向它添加了一个 WPF 文本框并将 CanExecuteChanged 处理程序附加到它:

public Form1()
{
   InitializeComponent();

   var tb = new System.Windows.Controls.TextBox {Text = "WPF Inside ElementHost"};

    ApplicationCommands.Cut.CanExecuteChanged += Cut_CanExecuteChanged;
    ApplicationCommands.Cut.CanExecuteChanged +=
        (s, e) => Debug.WriteLine("CanExecute Changed=" + ApplicationCommands.Cut.CanExecute(null, s as IInputElement));

    elementHost1.Child = tb;
}

private void Cut_CanExecuteChanged(object sender, System.EventArgs e)
{
    Debug.WriteLine("CanExecute Method for Cut = " + ApplicationCommands.Cut.CanExecute(null, sender as IInputElement));
}

奇怪的是,当我执行诸如在文本框中选择文本之类的操作时,会调用使用内联 lambda/delegate 的处理程序。但是,使用实例方法订阅的那个不会被调用。

此外,在我更复杂的应用程序中,我根本没有看到 CanExecute 被调用,即使我为处理程序使用内联委托也是如此。

4

1 回答 1

3

(以StackOverflow当橡皮鸭为例,写完问题我才明白答案)

虽然反射了一点,但我看到 CanExecuteChanged 事件只是将处理程序传递给CommandManager.RequerySuggested。因为后面的事件是静态事件,所以它使用Wea​​kReference处理程序并在引发事件时修剪列表。由于我没有在课堂上保留硬引用,因此 GC 检测到该引用不再有效并且正在被修剪。

解决方案只是添加一个具有 EventHandler 的类成员变量,然后在附加事件时使用该成员变量引用。

于 2010-07-12T18:15:14.973 回答