Любой WinRT iCommand/CommandBinding реализует образцы там?

Абстрактные команды в Модели просмотра являются ценной практикой с проектами XAML/MVVM. Я понимаю. И я вижу, что ICommand находится в WinRT; но как мы его реализуем? Я не нашел образец, который действительно работает. Кто-нибудь знает?

Ответы

Ответ 1

Мое любимое время всегда должно быть DelegateCommand, предоставленное командой PnP. Он позволяет создать типизированную команду:

MyCommand = new DelegateCommand<MyEntity>(OnExecute);
...
private void OnExecute(MyEntity entity)
{...}

Он также позволяет создать способ для события CanExecuteChanged (для отключения/включения команды)

MyCommand.RaiseCanExecuteChanged();

Здесь код:

public class DelegateCommand<T> : ICommand
{
    private readonly Func<T, bool> _canExecuteMethod;
    private readonly Action<T> _executeMethod;

    #region Constructors

    public DelegateCommand(Action<T> executeMethod)
        : this(executeMethod, null)
    {
    }

    public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
    {
        _executeMethod = executeMethod;
        _canExecuteMethod = canExecuteMethod;
    }

    #endregion Constructors

    #region ICommand Members

    public event EventHandler CanExecuteChanged;

    bool ICommand.CanExecute(object parameter)
    {
        try
        {
            return CanExecute((T)parameter);
        }
        catch { return false; }
    }

    void ICommand.Execute(object parameter)
    {
        Execute((T)parameter);
    }

    #endregion ICommand Members

    #region Public Methods

    public bool CanExecute(T parameter)
    {
        return ((_canExecuteMethod == null) || _canExecuteMethod(parameter));
    }

    public void Execute(T parameter)
    {
        if (_executeMethod != null)
        {
            _executeMethod(parameter);
        }
    }

    public void RaiseCanExecuteChanged()
    {
        OnCanExecuteChanged(EventArgs.Empty);
    }

    #endregion Public Methods

    #region Protected Methods

    protected virtual void OnCanExecuteChanged(EventArgs e)
    {
        var handler = CanExecuteChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    #endregion Protected Methods
}

Ответ 2

Отъезд RelayCommand class (только код METRO). Класс NotifyPropertyChanged можно найти здесь. Класс NotifyPropertyChanged используется только для привязки на CanExecute и обновляет его с помощью RaiseCanExecuteChanged.

Исходный класс команд реле можно найти здесь

Ответ 3

К сожалению, похоже, что нет родного класса, который реализует его для вас. Интерфейс не слишком сложный, если вы хотите его реализовать самостоятельно, а популярный инструментарий MVVM Lite включает в себя собственную версию RelayCommand. Вы можете добавить MVVM Lite в свой проект, щелкнув правой кнопкой мыши ссылку и выбрав "Управление пакетами NuGet". Если у вас нет этой опции, включите Nuget под Инструменты → Расширения и обновления.

Ответ 4

Я искал минимальную сквозную реализацию команды XAML-MVVM и еще не нашел ее.

Итак, после ответа #Rico у меня получилось следующее как минимальная RelayCommand, которая работает. Я использую аналогичную минимальную версию в большом проекте.

public class RelayCommand : System.Windows.Input.ICommand {

    readonly Action<object> execute; 

    public RelayCommand(Action<object> execute) {
        this.execute = execute;
    }

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

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter) {
        this.execute(parameter);
    }
}

Чем больше класс RelayCommand предоставляет больше контроля над CanExecute и CanExecuteChanged, но для этого вам не нужно, и вам может вообще не понадобиться.

Чтобы использовать его в модели просмотра:

class ViewModel : INotifyPropertyChanged {

    << ... snip VM properties and notifications ...>>

    public RelayCommand DoSomethingCommand {
        get {
            return new RelayCommand(param => {
                this.DoSomething(param as AType);
                Debug.WriteLine("Command Executed");
            });
        }

    }
}

(Нам не нужен INotifyPropertyChanged для Command, но любая модель представления обычно реализует его.)

Наконец, XAML...

   <Grid>
        <!-- Set the data context here, for illustration. -->
        <Grid.DataContext>
            <local:ViewModel/>
        </Grid.DataContext>
        <!-- A sample control bind to a property -->
        <TextBlock 
             Text="{Binding AProp}"/>
        <!-- Bind a command -->
        <Button Command="{Binding DoSomethingCommand}" CommandParameter="foo">Change!</Button>
    </Grid>

Ответ 5

Я нашел этот действительно хороший пример в https://code.msdn.microsoft.com/windowsapps/Working-with-ICommand-690ba1d4

<Page.Resources> 
        <local:MyCommandsCollection x:Key="MyCommands" /> 
</Page.Resources> 

   <Button Width="280" 
            Height="59" 
            Margin="513,280,0,0" 
            HorizontalAlignment="Left" 
            VerticalAlignment="Top" 
            Command="{Binding MyFirstCommand}" 
            CommandParameter="{Binding Text, 
                                       ElementName=myTextBox}" 
            Content="Execute Command" /> 


public class MyCommandsCollection 
{ 
    public MyCommand MyFirstCommand 
    { 
        get { return new MyCommand(); } 
    } 
} 

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

        public event EventHandler CanExecuteChanged; 

        public async void Execute(object parameter) 
        { 
            MessageDialog message = new MessageDialog( 
                "The command is executing, the value of the TextBox is " + parameter as String); 
            await message.ShowAsync(); 
        } 
    }

Я пробовал это с помощью x: Bind, и он работает хорошо. Все, что мне нужно, - это открыть свойство в моей модели ViewModel, которая возвращает новый экземпляр класса "MyCommand", и все это хорошо.

Поскольку я устанавливаю DataContext в свой XAML, мне не нужно было связываться с каким-либо материалом "MyCommandCollection". Yay скомпилировал привязку.