任何WinRT iCommand / CommandBinding实现了那里的样本?

时间:2012-08-14 20:48:42

标签: windows-8 winrt-xaml

将命令抽象到视图模型中是XAML / MVVM项目的一项有价值的实践。我明白了。而且,我在WinRT中看到了ICommand;但是,我们如何实现它?我还没有找到实际可行的样本。有人知道吗?

5 个答案:

答案 0 :(得分:20)

我最喜欢的是Microsoft模式和实践团队提供的DelegateCommand。它允许您创建一个类型化的命令:

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
}

答案 1 :(得分:3)

查看RelayCommand课程(仅限METRO代码)。可以找到NotifyPropertyChanged课程hereNotifyPropertyChanged类仅用于允许CanExecute上的绑定,并使用RaiseCanExecuteChanged进行更新。

可以找到原始中继命令类here

答案 2 :(得分:2)

不幸的是,似乎没有为您实现它的本机类。如果你想自己实现它,界面不是太复杂,流行的 MVVM Lite 工具包包含自己的 RelayCommand 版本。您可以通过右键单击References并选择“Manage NuGet Packages”将MVVM Lite添加到您的项目中。如果您没有此选项,请在工具 - &gt;下启用Nuget。扩展程序和更新

答案 3 :(得分:0)

我一直在寻找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类似乎可以提供对CanExecuteCanExecuteChanged的更多控制权,但您并不需要这样做才能开始使用 - 您可能根本不需要它。

要在视图模型中使用它:

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,但任何视图模型通常都会实现它。)

最后,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>

答案 4 :(得分:0)

我发现这是一个非常好的例子 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”类实例,这一切都很好。

由于我在我的XAML中设置了DataContext,所以我不需要搞乱任何“MyCommandCollection”的东西。 Yay编译绑定。