Событие RoutedCommand.CanExecuteChanged не всегда запускается внутри ElementHost - PullRequest
1 голос
/ 12 июля 2010

(Справочная информация: я портирую приложение WinForms на WPF поэтапно. В настоящее время у меня все еще есть основная форма WinForms с ElementHost, в которой есть содержимое WPF.)

Я быкак мое приложение, когда мне сообщают, когда определенные ApplicationCommands , такие как Cut , Copy и Paste , изменяют значение своих .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));
}

Странно то, что вызывается обработчик, использующий встроенный лямбда / делегат, когда я выполняю такие действия, как выбор текста в текстовом поле,Однако тот, который подписывается с использованием метода экземпляра, не вызывается.

Кроме того, в моем более сложном приложении я не вижу вызова CanExecute вообще, даже когда я использую встроенный делегат дляобработчик.

1 Ответ

3 голосов
/ 12 июля 2010

(В случае использования StackOverflow в качестве резиновой утки я понял ответ, когда закончил писать вопрос)

Немного подумав, я увидел, чтоСобытие CanExecuteChanged просто передает обработчик в CommandManager.RequerySuggested .Поскольку это более позднее событие является статическим, оно использует обработчики WeakReference и удаляет список при его возникновении.Так как в классе я не хранил жестких ссылок, ГК обнаружил, что ссылка больше не действительна и ее сокращают.

Решением было просто добавить переменную-член класса, в которой был EventHandler, а затем использовать ссылку на эту переменную-член при присоединении события.

...