Подтвердить что ты не робот

Когда вызывается CanExecute?

В демонстрации у меня есть кнопка для переключения поля bool isAsking. Я создаю команду, которая может выполняться только тогда, когда isAsking==true.

Как только я нажимаю кнопку Toggle, okButton.IsEnable немедленно изменяется, что указывает, что команда находит изменение isAsking.

Я очень смущен, почему объект команды замечает изменение поля, когда CanExecute будет вызываться?

Несмотря на то, что я накладываю приложение WPF на некоторое время, я новичок в WPF Command. Просьба дать объяснение этому делу и, если возможно, указать некоторые связанные статьи или блоги (я уже читал слишком много статей о команде cut/paste).

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Class="WpfApplication1.MainWindow"
        Title="MainWindow" Height="350" Width="525" x:Name="mainWindow" >
    <StackPanel>
        <Button Name="okButton" Content="Ok" />
        <Button Content="Toggle"  Click="Button_Click_1"/>
    </StackPanel>
</Window>

Code-за:

public partial class MainWindow : Window
{
    private bool isAsking;

    public MainWindow()
    {
        InitializeComponent();

        CommandBinding cb = new CommandBinding();
        cb.Command = okCommand;
        cb.CanExecute += CanOKExecute;
        cb.Executed += cb_Executed;
        mainWindow.CommandBindings.Add(cb);
        okButton.Command = okCommand;
    }

    private RoutedCommand okCommand = new RoutedCommand("ok", typeof(MainWindow));


    void cb_Executed(object sender, ExecutedRoutedEventArgs e)
    {

    }

    void CanOKExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = isAsking;
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        isAsking = !isAsking;
    }
}
4b9b3361

Ответ 1

Я пытаюсь найти "CommandManager обнаруживает условия" и достигает этой замечательной статьи.

Изучая исходный код .NET Framework, автор обнаруживает, что CommandManager не определяет условия сам по себе, а не когда Keyboard.KeyUpEvent, Mouse.MouseUpEvent, Keyboard.GotKeyboardFocusEvent или Keyboard.LostKeyboardFocusEvent происходит, это будет переоценить метод CanExecute.

В этой статье содержится другая информация, но для меня эта часть была достаточно.

Ответ 2

Технический ответ заключается в том, что CanExecute будет вызываться всякий раз, когда возникает событие CommandManager.RequerySuggested. Согласно документации, это будет...

... когда CommandManager обнаруживает условия, которые могут изменить возможность выполнения команды.

В практическом плане это просто означает, что вам не нужно беспокоиться о том, когда вызывается CanExecute: WPF будет ссылаться на него, когда он считает, что это уместно, и по моему опыту это почти всегда будет отвечать вашим требованиям.

Исключением является то, что если у вас есть фоновая задача, которая заставит CanExecute изменить его возвращаемое значение на основе чего-то, что не запускается пользовательским интерфейсом. В этом случае вам может потребоваться вручную заставить среду выполнения WPF повторно запросить CanExecute, которую вы можете сделать, вызвав CommandManager.InvalidateRequerySuggested

Ответ 3

RoutedCommand содержит событие CanExecuteChanged, которое внутренне привязывается к событию CommandManager.RequerySuggested -

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

Истекло событие CommandManager.RequerySuggested

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

Кроме того, CommandManager имеет статический метод - InvalidateRequerySuggested, который заставляет CommandManager поднять RequerySovedEvent. Таким образом, вы можете вызвать это, чтобы проверить свои команды слишком вручную.