Есть ли чистый способ заставить CanExecute всегда возвращать true с атрибутом? - PullRequest
1 голос
/ 03 марта 2010

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

Теперь я нахожусь в ситуации, когда я не хочу, чтобы какая-либо логика выполнялась, потому что выполнение приводит к вызовам библиотеки, которую я не хочу выполнять только для обновлений GUI . Я не могу заглушить вызовы библиотеки, потому что они важны для функциональности остальной части приложения.

Я посмотрел на условные атрибуты в .NET, и, к сожалению, это не сработает, потому что они работают только с методами, возвращающими void. Я мог бы использовать #if и #define, чтобы использовать мою логику или просто вернуть true. Я также мог бы запросить свойство в viewmodel и позволить ему определить, стоит ли просто возвращать true.

Проблема в том, что я не ленивый, но я также не хочу делать кучу тяжелой работы, чтобы сделать модификации, которые я предполагаю, неизбежны. Однако, если кто-то знает способ использования чего-либо в .NET для автоматического включения моих кнопок без необходимости вызывать CanExecute или, по крайней мере, избегать использования базовой логики, пожалуйста, опубликуйте ответ! :)

Ответы [ 2 ]

1 голос
/ 03 марта 2010

Я спрашиваю, почему не стоит заходить в эту библиотеку для логики графического интерфейса. Вы не хотите включать кнопки, которые ничего не будут делать, поэтому команды, которые отключены, когда они фактически не могут работать, могут быть полезны.

При использовании шаблона MVVM мои ViewModels обычно предоставляют ICommands напрямую. Если вы используете Prism, существует реализация DelegateCommand, которая позволяет легко реализовать эти команды в ваших ViewModels. Если нет, или если CanExecute может измениться, я бы реализовал ICommand в отдельном классе.

Если у вас длительная / дорогостоящая операция, вы всегда можете кэшировать результат вызова библиотеки. Я предполагаю, что вы получите событие или обратный вызов, если состояние изменится, что позволит включить / отключить команду. В этом случае в вашей реализации ICommand вы бы вызвали событие CanExecuteChanged, чтобы графический интерфейс отражал изменения в команде. Вот пример команды, которая использует службу поддержки, которая знает, когда операция может быть завершена:

public class ExpensiveCommand : ICommand
{
    private readonly IExpensiveService service;
    private bool canExecute;

    public ExpensiveCommand (IExpensiveService service)
    {
        this.service = service;
        canExecute = service.CanExecute();
        service.CanExecuteChanged += OnCanExecuteChanged;
    }

    public void Execute(object parameter)
    {
        service.Execute();
    }

    public bool CanExecute(object parameter)
    {
        return canExecute;
    }

    public event EventHandler CanExecuteChanged;
    private void OnCanExecuteChanged(object sender, EventArgs e)
    {
        canExecute = service.CanExecute();

        if (CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }
}

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

0 голосов
/ 03 марта 2010

Я не знаю, есть ли способ с атрибутом, но попробуйте это.Где-то в окне кода запуска цикла переберите все привязки команд и обработайте событие PreviewCanExecute для каждого из них.

public MainWindow()
{
    foreach (CommandBinding cb in CommandBindings)
    {
        cb.PreviewCanExecute += new CanExecuteRoutedEventHandler(cb_PreviewCanExecute);
    }
}

void cb_PreviewCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = false; // disable / enable all commands
    e.Handled = true; // Set this to skip calling your existing logic
}
...