Получить статус выполнения ICommand в WPF для обновления текста на xaml - PullRequest
0 голосов
/ 27 января 2020

У меня есть модель вида, которая выглядит следующим образом:

public sealed class MyViewModel: INotifyPropertyChanged
{
    public bool ShowSuccess 
    {
        get { return _success; } 
        set 
        { 
            _success = value; 
            PropertyChanged?.Invoke( ... );
        } 
    }

    public ICommand TestCommand 
    {
      get
      {
        _test = _test ?? new MyTestCommand();
        return _test;
      }
    }
}

и команда

public sealed class MyTestCommand : ICommand
{
    public bool CanExecute(object parameter)
    {
      return true;
    }

    public void Execute(object parameter)
    {
       // do stuff
    }
}

и в xaml

 <Button Command="{Binding TestCommand}" Content="Test" />

Я хочу обновить ShowSuccess свойство после выполнения Execute из MyTestCommand.

Как этого добиться?

Спасибо

PS: я все еще новичок ie в WPF, только что выучил MVVM и пользовательскую команду

Ответы [ 2 ]

0 голосов
/ 27 января 2020

Я настоятельно рекомендую взглянуть на ReactiveUI - инфраструктура пользовательского интерфейса, основанная на Rx - вам не нужно использовать все ее функции, такие как встроенное внедрение зависимостей или расположение представления, но это также очень круто , В этом случае не стоит изобретать колесо.

Он имеет реализацию ICommand, которая не только поддерживает асинхронную работу из коробки, но также позволяет командам возвращать вещи (ОЧЕНЬ полезно) и заботится об отключении кнопки при выполнении.

Он также поставляется с DynamicData - лекарство от всех проблем, связанных с коллекциями.

Итак, большинство базовых c примеров будут:

TestCommand = ReactiveCommand.CreateFromTask<int>(async paramater  =>{
   var result = await DoStuff(parameter); // ConfigureAwait(false) might be helpful in more complex scenarios

   return result + 5;
}

TestCommand.Log(this) // there is some customization available here
   .Subscribe(x => SomeVmProperty = x;); // this always runs on Dispatcher out of the box

TestCommand.ThrownExceptions.Log(this).Subscribe(ex => HandleError(ex));

this.WhenAnyValue(x => x.SearchText) // every time property changes
   .Throttle(TimeSpan.FromMilliseconds(150)) // wait 150 ms after the last change
   .Select(x => SearchText) 
   .InvokeCommand(Search); // we pass SearchText as a parameter to Search command, error handling is done by subscribing to Search.ThrownExceptions. This will also automatically disable all buttons bound to Search command

Что еще более полезно, я думаю, это возможность подписаться в коде View позади.

// LoginView.xaml.cs

ViewModel.Login.Where(x => !x.Success).Subscribe(_ =>{
   PasswordBox.Clear();
   PasswordBox.Focus();
});
0 голосов
/ 27 января 2020

Вы можете использовать DelegateCommand для этого. Это помогает вам использовать один класс Generi c для всех команд вместо создания отдельных классов команд.

public sealed class MyViewModel : INotifyPropertyChanged
{
    private ICommand _test;
    private bool _success;

    public bool ShowSuccess
    {
        get { return _success; }
        set
        {
            _success = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ShowSuccess)));
        }
    }

    public ICommand TestCommand
    {
        get
        {
            _test = _test ?? new DelegateCommand((arg) => ShowSuccess = true);
            return _test;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

public class DelegateCommand : ICommand
{
    private readonly Predicate<object> _canExecute;
    private readonly Action<object> _execute;

    public event EventHandler CanExecuteChanged;

    public DelegateCommand(Action<object> execute)
                   : this(execute, null)
    {
    }

    public DelegateCommand(Action<object> execute,
                   Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        if (_canExecute == null)
        {
            return true;
        }

        return _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...