添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
火爆的罐头  ·  Hive ...·  2 月前    · 
呐喊的皮蛋  ·  第02篇 ...·  4 月前    · 
乐观的春卷  ·  Vue Cli 中使用 jQuery - ...·  5 月前    · 
豁达的充电器  ·  JS Map 映射(ES6)_js ...·  1 年前    · 
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 application using a mvvm-approach it's pretty common that the ViewModel provides one or more Command -properties. These properties often have the type ICommand or DelegateCommand or something like that.

I don't understand why we need such an approach in an mvvm application. Wouldn't it be enough to provide public methods and bind the action from the view directly to this public method?

Why does ICommand exist?

"bind the action from the view directly to this public method" - that's what ICommand does as well as tells the View whenever command can be executed. Have a look at DelegateCommand it makes it simple. Sinatr Feb 8, 2017 at 12:44 Some MVVM frameworks like Caliburn.Micro use naming conventions to bind methods to view elements without an ICommand. Panagiotis Kanavos Feb 8, 2017 at 12:51 One can add own functionality relatively easily with attached behaviors (pure MVVM): you can subscribe to certain View events (you can do it in the View code-behind, but that would be dirty MVVM) to call certain methods of ViewModel (directly, via interface or using reflection). ICommand was a bare minimum what WPF needs, namely it solves problem when menu items/buttons become disabled e.g. for Copy / Paste scenario. Nothing more. In fact ButtonBase.Command can be a simple Click event handler, you can right away call ViewModel method there. Sinatr Feb 8, 2017 at 13:13
  • you can't bind to a method in xaml. You need an object. Therefore you need to wrap the method to an object.

  • it is a common pattern in UI, that some actions are not available all the time. In Login form the Login action become available only when you enter username. In MS Word, the Copy or Cut actions becomes available only when you select something, otherwise the buttons are disabled and keyboard shortcuts inactive

  • it is a common pattern, that command can be invoked with different parameters.
  • Plain eventhandlers does not meet those requirements, But ICommand servers exactly those purposes:

    public interface ICommand
        void Execute(object parameter);
        bool CanExecute(object parameter);
        event EventHandler CanExecuteChanged;
    
  • It wraps method to an object
  • It says whether to command is available or no, so the UI component (typically a button or menuitem) can reflect it
  • Additionally, it notifies the UI components that the availability of the command has changed, so the UI can reflect it.
  • Now, let's consider Copy&Paste scenario. Using ICommand the markup can look like this:

    <Button Content="Paste" Command="{Binding PasteCommand}" />
    <MenuItem Header="Paste" Command="{Binding PasteCommand}" />
    
    public ICommand PasteCommand {get;} = new DelegateCommand(Paste, () => Clipboard != null);
    

    How would it look like without ICommand? To make it easier, lets consider, that XAML would allow to bind to methods:

    <Button Content="Paste" Click="{Binding Paste}" IsEnabled="{Binding CanPaste}" />
    <MenuItem Header="Paste" Click="{Binding Paste}" IsEnabled="{Binding CanPaste}"/>
    public void Paste() {....}
    private bool _canPaste;
    public bool CanPaste
        get { return _canPaste }
            if (_canPaste != value)
                _canPaste = value;
                OnNotifyPropertyChanged(nameof(CanPaste);
    

    as you can see, not only it is more verbose, but it's also violation of DRY principle. You need to specify both Paste and CanPaste binding every time you want to use the command. What if you started without CanPaste and later you wanted to add it. Then you would have to add the CanPaste binding every occurrence of the Paste call. I guarantee you, that you would forget it somewhere.

    Now, if you did this in WPF:

    <Button Content="Paste" Click="Call_ViewModel_Paste" />
         <i:Interaction.Triggers>
             <i:EventTrigger EventName="Click">
                 <ei:CallMethodAction MethodName="Paste" TargetObject="{Binding}"/>
             </i:EventTrigger>
         </i:Interaction.Triggers>
    </Button>
    

    Both approaches are correct, they follow MVVM priciples and works without ICommand, but as you can see, neither is as elegant as ICommand

    Wouldn't it be enough to provide public methods and bind the action from the view directly to this public method?

    How would you for example call a public method when a Button in the view is clicked?

    The answer is that you bind the Command property of the Button to an ICommand property of the view model that calls the method for you. That's the main reason why any actions that view model defines are exposed using commands.

    A command is nothing but an object that implements the System.Windows.Input.ICommand interface and encapsulates the code for the action to be performed.

    Please refer to the following links for more information about the concept.

    https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/ https://msdn.microsoft.com/en-us/magazine/dn237302.aspx

    »A command is nothing but an object that ... encapsulates the code for the action to be performed.« – But that's exactly what it isn't, is it? A command is just a marker of sorts, the actual action comes from a command binding. – Joey Feb 8, 2017 at 13:09 You don't use a System.Windows.Input.CommandBinding in MVVM. You bind to a property of the view model that returns an ICommand object and then the Execute method of this ICommand object is invoked when you for example click on a button in the view. – mm8 Feb 8, 2017 at 13:13 How does this answer why WPF commands work the way they do? It looks like the OP is asking why we can't write {Binding MethodName} instead of {Binding CommandObject}. – Pieter Witvoet Feb 8, 2017 at 13:20

    In MVVM you try to avoid "code behind" (this is code in the MyView.cs file) to avoid a tight coupling of View, ViewModel and Model.

    In MFC you just registered an event handler (which is still possible in WPF), but in MVVM there is the possibility of just binding a ICommand which will be executed instead of triggering the event.

    you could bind View to a method in ViewModel. Actually, you can do it using CallMethodAction in xaml. So this is not really an answer why we need ICommand – Liero Feb 8, 2017 at 13:11 But a command is much more flexible, cause it is a whole class which can be customized. E.g. using other properties etc. – Traummaennlein Feb 8, 2017 at 13:14

    Short: ex. Buttons Buttons works by creating event (Click="XEvent") that consist of method and then we tell application what to do next i.e. call other methods obviously that works with Code behind. (Event => method is generated at MainWindow.xaml.cs .)

    In MVVM we avoid code behind pattern. to achieve that we need to set the DataContext to other class (will act as middleware) say MainWindowViewModel.cs .

    By implementing ICommand interface and implementing methods to handle the command we avoid code behind maintain MVVM pattern.

    Well there can be alternative to ICommand interface like to bind method in ViewModel to command in XAML (Wont prefer though)

    <Button Command="{ViewModel AnyMethodName}"/>

    ICommand interface will provide you CanExecute method which can be used to enable/Disable controllers simple delegate wont give u that functionality Hope this helps :)

    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.