I've been seeing tutorials where people are creating the methods like CanExecute in their code. I'm assuming they are doing this to help the reader understand how it all works. When I look up Command and ICommand it takes me to the ICommand class on MSDN that is used for Windows Store apps. Is there not a Command class for WPF?
The built-in implementation of ICommand in WPF is RoutedCommand (and its sibling RoutedUICommand). RoutedCommand works like this:
The Execute and CanExecute methods on a RoutedCommand do not contain
the application logic for the command as is the case with a typical
ICommand, but rather, these methods raise events that traverse the
element tree looking for an object with a CommandBinding. The event
handlers attached to the CommandBinding contain the command logic.
The problem with this is that these event handlers must be attached to the code-behind for your view, which is exactly what you do not want to do in MVVM.
Tutorials where you see CanExecute methods in code (and by that we really mean code outside the ICommand implementation) are using custom command implementations such as DelegateCommand and RelayCommand which are designed to "forward" their CanExecute/Execute logic to functions provided on the fly; typically, those are methods on the viewmodel that exposes the command.
These implementations are usually provided by MVVM frameworks (for these two examples the frameworks are Prism and MVVM Light respectively), but they are really simple (both are open source, grab the code and read it) and there's nothing stopping you from copy/pasting the code if you don't want the whole of the framework.
You could summarize the above as "there is built-in a command class in WPF, but it's not really useful in the context of MVVM".
Related
I am struggling with MVVM in my application. I have there a TabControl whose every Tab hosts a control that allows somehow editing a file. For instance, text files or images. Each control is bound to a class from ViewModel area (as is depict at the diagram). I also have RoutedUICommands. One of these commands is WordWrap and only makes sense in case of text files. This command is used in MenuItem or a Button etc. I'd like to enable it only if a text control is the target for this command. How to do it properly according to MVVM?
More details:
XAML for the Window has:
<Window.CommandBindings>
<CommandBinding Command="local:EditorCommands.WordWrap"
Executed="WordWrapExecuted"
CanExecute="CommandCanBeExecutedWhenAnythingIsOpen"/>
</Window.CommandBindings>
A menu item is used this way:
<MenuItem Command="local:EditorCommands.WordWrap"/>
The first thing is the Executed and CanExecute event handlers: they are in Window class although my understanding if MVVM is, that the logic should be in ViewModel only.
What's more, the sender in these function is an instance of a window. Why is it not a target of the command?
Should I write my own successors of RoutedUICommand for every command?
A RoutedUICommand is not really suited to be used in a view model as it searches the visual tree from the focused element and up for an element that has a matching System.Windows.Input.CommandBinding object in its CommandBindings collection and then executes the Execute delegate for this particular CommandBinding.
Since the command logic should reside in the view model, you don’t want to setup a CommandBinding in the view in order to connect the command to a visual element.
Instead, you should create your own implementation of the ICommand interface or use one that is available in any of the MVVM frameworks out there. MvvmLight for example has a RelayCommand class: https://msdn.microsoft.com/en-us/magazine/dn237302.aspx.
How to use RelayCommand with the MVVM Light framework
And in Prism it is called DelegateCommand:
https://www.codeproject.com/Articles/1055060/DelegateCommand-and-CompositeCommand-in-Prism
Please refer to the following blog post for more information about commands in MVVM: https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/
Iam using MVVM and have a main window with Close button and it is bound to the MainWindowViewModel's ICommand command.
In the main window there are two UserControl1 and UserControl2 which is bound to viewmodels UserControlVM1 and UserControlVM2 respectively.
UserControlVM1 and UserControlVM2 has command named CleanUp that will clean up the resources.
So Whenever the close button is clicked on the mainwindow, i wanted to call the CleanUp command of Usercontrol viewmodels. How can we do this in XAML or any other alternatives?
A common implementation for communication between ViewModels is the Mediator Pattern which describes an object common between your ViewModels providing a Publish/Subscribe model. When an Event of interest occurs in an object it publishes a notification to the Mediator, one or more objects that are subscribed to that particular Event of the Mediator are then notified of the Event occurring in the original object.
Mediator Pattern Example
You should consider a view model first approach, in which case the MainWindowViewModel would have references to the UserControlVM1 and UserControlVM2, and can call the CleanUp methods directly.
You should consider using an MVVM framework if you're using MVVM.
You could inspire yourself from a technique from Prism's developer guide.
In Patterns and Practices' Prism Framework, CompositeCommand allows several ViewModel to register their own command against a single CompositeCommand, so that all can be called with one single call.
You'd also need this global class that is referenced in all your ViewModels, but not necessarily a static one since you don't have loose coupled modules.
Let's have a button Command property bound to a custom command.
When should I implement ICommand and when derive from RoutedCommand? I see that RoutedCommand implements ICommand.
In which case could I need to implement an ICommand?
What about MVVM model? Which one suits better for this purpose?
As you have noticed the RoutedCommand class is an implementation of the ICommand interface, its main distinction if that its function is similar to that of a RoutedEvent:
The Execute and CanExecute methods on a RoutedCommand do not contain the application logic for the command as is the case with a typical ICommand, but rather, these methods raise events that traverse the element tree looking for an object with a CommandBinding. The event handlers attached to the CommandBinding contain the command logic.
The Execute method raises the PreviewExecuted and Executed events. The CanExecute method raises the PreviewCanExecute and CanExecute events.
In a case when you don't want the behavior of the RoutedCommand you'll be looking at your own implementation of ICommand. As for the MVVM pattern I can't say that one solution, it seems that everyone has their own methodology. However, here are a few approaches to this problem that I've come across:
Using RoutedCommands with a ViewModel in WPF
Relaying Command Logic
Simple Command (almost identical to Relay Command but worth reading)
The only thing I would add to Rich McGuire's answer is that RoutedCommands (and their more prevalent descendant RoutedUICommand have to be wired up with event handlers to work correctly.
Most MVVM implementations I have come across attempt to leverage binding against the ViewModel and thus the ViewModel (and not the View) owns the CanExecute/Execute logic.
In contrast, the event handlers move that burden to the View. The handling can then be propagated to the ViewModel, but this means a slightly higher degree of coupling between ViewModel and View (casting + method call, etc.).
I have begun creating a wpf mvvm app. It seems a vital ingredient to the ViewModel is a bunch of ICommands to have a loosely coupled way of allowing the view to interact with the viewmodel.
My question is this, why can't I bind directly to a method?
I have used Josh Smith's RelayCommand implementation of ICommand that allows you to inject delgates into an ICommand object, but really, is there some easier way to allow a button push to call a method in the viewmodel?
I'm new to MVVM, I believe I need some enlightenment
You can't bind directly to a method because Button (for example) doesn't have a property that accepts a delegate. Instead, it has a Command property of type ICommand. A RelayCommand (aka DelegateCommand) is just an ICommand that wraps delegates.
I see no technical reason why it wouldn't be possible for the view to bind to specific methods on the view model by way of a markup extension:
<Button Command="{ViewModelMethod SomeMethodName}"/>
However, this would be slower and would increase the coupling between the view and view model. If the view knows only about a property on the view model of type ICommand, the implementation of that command could change completely (or methods could be renamed) without the view being aware.
I completely disagree.
The speed of invocation bears no relevance: commands are user interactions, they never require speed.
Argument about coupling is flawed too. How come {Binding MyProperty} is not coupling but {ViewMethod MyMethod} is?
Requirement of having specially crafted 'Commands' to be wrapped around methods is a silly one. Commands might be useful implementation under the cover, but we already have methods in C# and replacing them with something big and bulky is not right.
And that thing about MarkupExtension and Binding, it really is difficult. But it can be done. Actually, it is done, you can have a look at MethodCall project on CodePlex:
http://methodcallthing.codeplex.com/
You can use binding to choose 'this' for the method, and can use binding to fetch arguments. And all those are live, i.e. being calculated at the time the command is invoked. Another bonus feature is push-out result of method call, you can use binding for that too (OneWayToSource).
ICommand gives you CanExecute, which is needed for control enabling. A simple delegate does not. ICommand is the way to go.
Apparently Microsoft needed a Command to be something first-class, probably because they felt having the CanExecute was necessary for most applications. I disagree and think the CanExecute should have just been another DependencyProperty that you would bind to a property of your viewmodel, but hey, what do I know?
Possibly they also thought that there was a need to decouple the implementation of a command from the control's datacontext. Yet again this seems unnecessary to me because the logic should live near the data that is being operated on, as is a fundamental principal of OO.
Personally I avoid using commands in MVVM because of the mess you have to create to implement them. I just let the view's code-behind delegate events up to the viewmodel.
Due to the way in which the title of this question is worded, readers might arrive here looking for an alternative to ICommand, instead of just a way to bind a UI action directly to a method of a viewModel. (Which is of little value, since it leaves open the question of what to do with the 'CanExecute` part.)
The use of ICommand is problematic in and of itself because it is defined in Windows.Input, which means that in order to declare ICommands in your ViewModels you have to reference WPF and the kitchen sink from within your application logic, and once you have done that, any noob might notice that MessageBox and a vast array of other GUI functionality is available, and might start making use of it, resulting in a terrible mess of mixed application logic and presentation logic.
So, if you want to get rid of using System.Windows, then you need to get rid of ICommand, and if you want to get rid of ICommand, then you might be happy to know the following:
WPF (specifically, the XAML designer) does not require your viewModels to statically expose instances of the ICommand interface.
By statically here I mean that the designer does not need to be able to prove, during design time, using reflection, that your command objects implement the ICommand interface; instead, WPF checks at runtime to make sure that UI actions are bound to objects which do in fact turn out to implement ICommand.
So, in your viewModels (application logic) instead of the ICommand interface of WPF you can be using some Command interface of your own device, and all you need to ensure is that the class that you will be instantiating at runtime to implement your Command interface also implements ICommand to keep WPF happy. This way you can avoid including ICommand from within your ViewModels, and subsequently you might be able to avoid having to reference System.Windows in your application logic.
I've decoupled events in this WPF application in the following way.
What is the best way to continue decoupling?
Shell.xaml:
<Button x:Name="btnProcess"
Content="Process"
Margin="10"/>
Bootstrapper.cs:
public void Run()
{
Shell shell = new Shell(new Customer());
shell.Show();
}
Shell.xaml.cs:
public Shell(IPerson person)
{
InitializeComponent();
btnProcess.Click +=new RoutedEventHandler(person.Process);
}
Customer.cs:
public class Customer : IPerson
{
public void Process(object sender, RoutedEventArgs e)
{
Button theButton = (Button)sender;
theButton.Content = "Customer processed.";
}
}
The above code successfully decouples the view Shell from the model Customer:IPerson so that I can swap in e.g. a model Employee:IPerson etc. which handles "Processed" in its own way. That was the first goal.
But now:
how do I decouple the Processed method from talking specifically to a Button, so that it could also talk to a MenuItem or a ListView which fires the event in the view and so that it doesn't even have to be an element at all that calls it, e.g. a unit test class?
how do I alter other elements of the view other than the sender (Button), e.g. how would I alter the status bar in Shell? I see two ways:
I could either build a container which holds all views and inject the container in the Customer upon creation, then the customer can look in the container and manipulate the calling view anyway it wants (although I would have to somehow match the view that sent the event and the view in the container as the same one)
I could somehow send the whole view (Window object) to the Model with the eventargs when firing the event, although the Model would need some way of knowing (via interface) what kinds of regions were available to manipulate at runtime
How would you continue this application in the direction of a more decoupled design?
What pattern is this actually, e.g. MVC, MVP, MVVM? I only see a view (Shell) and a Model (Customer).
How would a Presenter fit in?
How would a ViewModel fit in?
How would a Controller fit in?
I suggest you to implement your event handling using commands instead of classic events.
Its very easy in WPF because the command pattern is already implemented, and you can tell all of your UI inputs (button, menu item...) that their command is [name of your command] and handle all of them in one place.
Cameron MacFarland did a good job here, but I can add a little.
When following M-V-VM, the tools in your box for decoupling are data binding, commands, attached behaviors and interfaces. Data binding should be self evident. You've already gotten a good description of commands, but I'd suggest you avoid RoutedCommand and stick with an ICommand implementation. Attached behaviors are attached DependencyProperty's that subscribe to events on the element they are attached to, and in this scenario would be used to relay event handling to the ViewModel. Interfaces give you the greatest flexibility, but you have to work out how to pass the interface to the ViewModel. The best way to learn all of this right now is to Google and to look at existing M-V-VM frameworks. Here's a list of frameworks:
Prism/Composite WPF (http://www.codeplex.com/CompositeWPF). This one comes from the Microsoft Patterns & Practices group. Lots of good stuff here, but one of the examples of the three things above that you can learn from here is how to use ICommand. Prism includes a DelegateCommand that implements ICommand and simplifies using commands from a ViewModel in M-V-VM.
Caliburn (http://www.codeplex.com/caliburn). Recently released, one of the key things you can learn from this one is how to use attached behaviors, which this library uses for it's "Actions".
Onyx (http://www.codeplex.com/wpfonyx). Disclaimer: I'm the author of this one. This one hasn't been released yet, though the current alpha source is available. This one provides a novel solution to the problem of how to provide interfaces to your ViewModel.
As Chen suggests, i'd look into the Command pattern: Routed commands
A working example from which i learned a lot can be found on Jaime Rodriquez his blog: Southridge
how do I decouple the Processed method from talking specifically to a Button
Commands. Put a command in the IPerson interface and call that command from the Shell's xaml.
how do I alter other elements of the view
Properties and Binding. If you have a property showing the state (processed/not processed) then you can use binding to display that property directly in the xaml.
How would you continue
I'd head more down the MVVM path by creating a ViewModel between the Shell and the IPerson. The ViewModel is designed to have 1) The properties needed for bindings, and 2) any Commands that need executing. The ViewModel is designed to provide the UI with what it needs from the Model.
What pattern is this
Currently? Nothing. I see only two objects, the View and the Model. You don't have a Presenter, Controller or ViewModel.
For WPF I prefer ViewModel. See this question for more info on MVVM.