相关文章推荐
烦恼的鸵鸟  ·  switch 语句 (C) | ...·  3 年前    · 
温暖的汤圆  ·  在asp.net ...·  3 年前    · 
温暖的机器人  ·  Receiving Error "SSL ...·  3 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

In my project, i'd like to use MVVM (& Commands). I've started learning about commands and implementation of ICommand.

I'd like to create implementation of ICommand without parameters. (To trigger loading of data/flushing of data etc. - I don't need any parameters to do it, so it just seems natural to try and create command without parameters)

This is the code I'm using:

using System.Windows.Input;
public class NoParameterCommand : ICommand
    private Action executeDelegate = null;
    private Func<bool> canExecuteDelegate = null;
    public event EventHandler CanExecuteChanged = null;
    public NoParameterCommand(Action execute)
        executeDelegate = execute;
        canExecuteDelegate = () => { return true; };
    public NoParameterCommand(Action execute, Func<bool> canExecute)
        executeDelegate = execute;
        canExecuteDelegate = canExecute;
    public bool CanExecute()
        return canExecuteDelegate();
    public void Execute()
        if (executeDelegate != null)
            executeDelegate();

But i got errors about not implementing the ICommand interface in the right manner ('XXX.YYYY.NoParameterCommand' does not implement interface member 'System.Windows.Input.ICommand.Execute(object)')

So I thought about doing it like this instead:

(Added the parameters that were missing from CanExecute and Execute)

public class NoParameterCommand : ICommand
    ...omitted - no changes here...
    public bool CanExecute(object parameter) //here I added parameter
        return canExecuteDelegate();
    public void Execute(object parameter)    //and here
        if (executeDelegate != null)
            executeDelegate();
  • IS THIS A GOOD WAY TO DO IT?
  • SHOULD I USE ANOTHER WAY? (IF SO, WHAT SHOULD I DO INSTEAD?)
  • This is a good way, except of course that it makes no sense to intialize your fields and events to null. Fields are null by default, as is the backing field behind the event. – Kris Vandermotten Oct 14, 2013 at 12:57 @KrisVandermotten It's just an old habit I can't get rid of. Didn't even realize it's there until you pointed it out. :) – mishan Oct 14, 2013 at 13:03

    Additional suggestions:

    Thinking about this again, I would improve your architecture by introducing an additional hierarchy level where CanExecute() and Execute() are abstract. From that class, derive your command class that invokes delegates.

    This way, you can decide later on whether you want to supply your logic for your parameterless commands via delegates or via subclassing your base command class.

    I was not sure if I'm doing it right. Better safe than sorry. Thank you for quick reply & suggestion, I'm going to use delegates this time - suits me better, but I'll keep it in mind. – mishan Oct 14, 2013 at 12:51

    I'm not really sure what your concern is. It is common to ignore the parameters in the ICommand interface.

    If you really want CanExecute and Execute methods that don't have parameters, you can implement the interface explicitly (rather than implicitly). The ICommand methods will still exist, but to anyone looking at your object from the outside, they won't be able to see those methods:

    bool ICommand.CanExecute(object parameter) { this.CanExecute(); }
    public bool CanExecute()
      //do work
    

    You are essentially hiding the interface implemenation. If someone wants to directly call the CanExecute method from the interface, they would have to type cast to ICommand in order to do it. You really don't gain anything in doing it this way, but if you are concerned with how your class looks to outside developers (e.g. you are developing an API), then this can make it look a little cleaner as you are letting them know you do not require any parameters.

    I just wasn't sure if I'm doing it right, so i asked. I'm new to WP8 development and i'm just learning how to do it. There are (literally) thousands of tutorials on the web, but I couldn't find if what I'm thinking about is right. – mishan Oct 14, 2013 at 12:58 private readonly Action _execute; private Func<bool> _canExecute; private Func<bool> _isVisible; public event EventHandler IsVisibleChanged; public event EventHandler CanExecuteChanged; public MyCommand(Action execute, Func<bool> canExecute = null, Func<bool> isVisible = null) _execute = execute; _canExecute = canExecute ?? True; _isVisible = isVisible ?? True; public void Execute() _execute(); public Func<bool> CanExecute _canExecute = value ?? True; CanExecuteChanged(this, new EventArgs()); get { return _canExecute; } public Func<bool> IsVisible _isVisible = value ?? True; IsVisibleChanged(this, new EventArgs()); get { return _isVisible; } bool ICommand.CanExecute(object parameter) return CanExecute(); void ICommand.Execute(object parameter) Execute();

    However, since the delegates usually don't change, I prefer an immutable version:

    [ImmutableObject(true)]
    public class MyImmutableCommand : ICommand
        private static bool True() { return true; }
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;
        private readonly Func<bool> _isVisible;
        [Obsolete("Will not be invoked, because the implementation never changes.")]
        public event EventHandler CanExecuteChanged;
        public MyImmutableCommand(Action execute, Func<bool> canExecute = null, Func<bool> isVisible = null)
            _execute = execute;
            _canExecute = canExecute ?? True;
            _isVisible = isVisible ?? True;
        public bool CanExecute()
            return _canExecute(); 
        public bool IsVisible()
            return _isVisible(); 
        public void Execute()
            _execute();
        bool ICommand.CanExecute(object parameter)
            return CanExecute();
        void ICommand.Execute(object parameter)
            Execute();
                    That's some extra code that is not supported out of the box. A better way is to use a property converter to convert the boolean IsEnabled to a visibility and use that converter in your binding.
    – MovGP0
                    Aug 31, 2020 at 21:54
                    Btw: this is not how I write commands anymore. I switched to using ReactiveCommand class from the ReactiveUI library. Using it in all my WPF, UWP and Blazor projects. Highly recommend to learn that library.
    – MovGP0
                    Aug 31, 2020 at 21:56
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid …

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.