Any WinRT iCommand/CommandBinding implementaiton samples out there?

戏子无情 提交于 2019-11-30 11:49:33

问题


Abstracting commands into the View Model is a valuable practice with XAML/MVVM projects. I get that. And, I see ICommand in in WinRT; but, how do we implement it? I haven't found a sample that actually works. Anyone know?


回答1:


My all time favorite has to be the DelegateCommand provided by the Microsoft Patterns and Practices team. It allows you to create a typed command:

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

It also provides a way to raise the CanExecuteChanged event (to disable/enable the command)

MyCommand.RaiseCanExecuteChanged();

Here's the code:

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:


Check out RelayCommand class (only METRO code). The NotifyPropertyChanged class can be found here. The NotifyPropertyChanged class is only used to allow bindings on CanExecute and update it with RaiseCanExecuteChanged.

The original relay command class can be found here




回答3:


Unfortunately there does not seem to be a native class that implements it for you. The interface is not overly complicated if you want to implement it yourself, and the popular MVVM Lite toolkit includes its own version of RelayCommand. You can add MVVM Lite to your project by right-clicking on References and choosing "Manage NuGet Packages". If you don't have this option, enable Nuget under Tools -> Extensions and Updates.




回答4:


I've been looking for a minimal end-to-end implementation of a XAML-MVVM command, and not found it yet.

So, following #Rico's answer I ended up with the following as a minimal RelayCommand which works. I use a similar minimal version in a large project.

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);
    }
}

The larger RelayCommand class seems to provide more control over CanExecute and CanExecuteChanged, but you don't need that to get started - and you may not need it at all.

To use it in a view model:

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");
            });
        }

    }
}

(We don't need the INotifyPropertyChanged for the Command, but any view model typically implements it.)

Finally, the 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:


I found this really good example at 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(); 
        } 
    }

I tried this out with x:Bind and it works nicely. All I need is to expose a property in my ViewModel that returns a new Instance of the "MyCommand" class and it's all good.

Since I'm setting the DataContext in my XAML, I didn't need to mess with any of the "MyCommandCollection" stuff. Yay compiled binding.



来源:https://stackoverflow.com/questions/11960488/any-winrt-icommand-commandbinding-implementaiton-samples-out-there

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!