I was talking to someone today about picking a design pattern for how to handle logic in their WPF program and hoping that the SO community can help with further advice to make the decision easier. What factors in favour of commands outweigh the inconvenience?
I prepared a full sample along with some UML diagrams of the first two of three approaches:
Use Click event handlers on buttons and menus.
Use commands bound in XAML.
Use commands bound in code, with the XAML kept for pure GUI layout and styling.
The introductory course he'd been on and many of the books show simple Click event handlers as the natural way to connect logic to UI objects.
He was a bit stunned by the amount of overhead required to use commands with both the command being created in the code behind file:
public static readonly ICommand cmdShow2 = new RoutedUICommand(
"Show Window2", "cmdShow2",
typeof(TestDespatchWindow));
and then even more code in the XAML with the wordy way the command has to be identified and bound:
<Window x:Class="WPFDispatchDemo.TestDespatchWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:w="clr-namespace:WPFDispatchDemo"..>
<Window.CommandBindings>
<CommandBinding Command="{x:Static w:TestDespatchWindow.cmdShow2}"
Executed="OnShow2" />
</Window.CommandBindings>
<DockPanel>
<StackPanel Margin="0,8,0,0">
<Button x:Name="Show2EventBased"
Margin="10,2,10,2"
Click="OnShow2"
Content="Show2 via WPF Event"/>
<Button x:Name="Show2Command"
Command="{x:Static w:TestDespatchWindow.cmdShow2}"
Margin="10,2,10,2"
Content="Show2 via WPF"/>
</StackPanel>
</DockPanel>
</Window>
I can't (yet) claim to be a WPF expert so I may have painted things as more complex than they really are but my suspicion is that you can't simplify things much more than the above.
Edit:
I found an interesting 3-way comparison between DelegateCommand, RoutedCommand and Event.
Commands their advantages and disadvantages, you have to choose based on your situation,
I highly recommend you make that choice on a case basis, don't choose "the one true way" for the entire project.
For some cases the separation between sender and receiver and the ability to send commands using only XAML is a big advantage (for a good example look how the ScrollBar control template communicates with the control logic at http://msdn.microsoft.com/en-us/library/ms742173.aspx ).
In other cases commands can turn what would have been a 2 lines event handler into some impossible to follow monstrosity involving changing 4 separate places in the application (How should the ViewModel close the form? ).
The only reason is to have well know registry of commands. Means that events are likely to be private methods and I feel that they are tightly bonded to code of the window. At the same time Commands gives ability to keep implementation (event) and definition (Command) separately, you can even use another class (take a look on ApplicationCommands).
In addition, when I am doing my WPF work I use implementation of the ICommand(Command Pattern). All logic of the command goes to the Execute method. This helps me to keep separation of logic in more structured way witout overcomplication of the window code. With this option you can create commands on your model and therefore bind them witout noise. Take a look.
Create model.
public class Model
{
ICommand CloseMessagePopupCommand {get; set;}
}
Then assign Data Context
public MainWindow()
{
this.DataContext = new Model();
}
And use follwing XAML code.
<Button
Command="{Binding CloseMessagePopupCommand}"
Content="{StaticResource Misc.Ok}" />
I try to stay true to the command pattern that Mike refers to when developing WPF applications, using a combination of Andy's #2 and #3 approaches.
I can think of only one downside of commands in my view: only certain actions of certain UI elements invoke commands. One way to get around this is to have your event handler call the Execute method on a command. I think that commands provide a very good way to encapsulate execution logic. If you maintain a large piece of UI and implement it using a MVC/MVC/MVVM pattern, this becomes very apparent.
I encourage you to take a look at Dan Crevier's series on the DataModel-View-ViewModel pattern, in particular the section on Commands and Encapsulating Commands. Even if this pattern doesn't meet your needs, it gives a great overview of how you can encapsulate logic inside a separate class.
Other variations on ICommand seem to be a popular way to implement complex command structures.
Brian Noyes in his article on PRISM says
Routed commands in WPF are very powerful and useful, but they have some shortcomings when applied to a composite application. The first is that they are entirely coupled to the visual tree-the invoker has to be part of the visual tree, and the command binding has to be tied in through the visual tree. ... The second shortcoming is that they are tightly tied in with the focus tree of the UI and goes on to talk about the DelegateCommand and CompositeCommand which CAL (Prism) includes.
Related
There's a WPF class called SystemCommands. I've seen examples of these commands being used on buttons to perform common window tasks like maximize, minimize and close.
One of the examples I found looked like this (simplified):
<Window x:Name="MainWindow">
<Grid>
<Button Content="Close"
Command="{x:Static SystemCommands.CloseWindowCommand}"
CommandParameter="{Binding ElementName=MainWindow}" />
</Grid>
</Window>
When I start the application the button is disabled and I can't click it. Changing the IsEnabled property has no effect.
I managed to get the button to be enabled once, but I'm not able to reproduce it now. In any case, when it was enabled, nothing happened when I clicked it.
What must I do to get this button enabled and to actually close the window (or minimize/maximize)? I would really prefer it to be a XAML only solution if this is possible.
These are only predefined RoutedCommand(s) without any implementation. You must provide the implementation by yourself.
https://msdn.microsoft.com/en-us/library/system.windows.systemcommands
The commands in the SystemCommands class represent a set of common
commands that manage a Window. The properties in this class represent
RoutedCommand objects and do not provide the implementation logic for
the command. You can provide the logic for a command by binding the
command with a CommandBinding. Alternatively, the SystemCommands class provides static methods that implement the logic for the specified Window. You can pass a static method to a type that implements ICommand and that accepts a delegate. For more information, see the example in the InputBinding class.
I saw an question here where OP asked about binding events to ViewModel. Basically ViewModel shall respresent an abstract View containing necessary data from Model so that the View may be also able to use Bindings. But to be able to fullfill all that the ViewModel must also conver most of the use cases which are happening in the View such as example if search textbox is empty the search button shall be greyed out. That works fine but lets add events to the game. It would be way easier if Button.Click where bindable to an EventHandler in ViewModel and inside the event handler you would be then able to use model objects.
Now my question is since WPF supports event driven programming why cant events be handled in ViewModel? How could I provide binding events funcionality?
Event handlers would sit in the view's code behind file. If you're using MVVM, then you'll want to minimise the amount of code in a code behind file.
WPF supports commanding, and the ICommand interface includes a CanExecute and Execute method. There are implementations of ICommand which allow these methods to be implemented on the view model.
Having said that, commanding also has its limitations, so you should consider using an MVVM framework when using MVVM. Something like Caliburn.Micro comes with Actions which also allow verbs on the view model to be invoked based on control events.
It is because the use of event explicitly breaks the MVVM pattern (as I am sure you are aware). However there is another way around this - by using the Attached Command Behaviour pattern. More information here.
Code for a small but great framework for attached commands is downloadable from here.
I hope this helps.
Edit. attached behaviour allow you to use events without breaking the MVVM pattern. The use is like
<Border Background="Yellow" Width="350" Margin="0,0,10,0" Height="35" CornerRadius="2" x:Name="test">
<local:CommandBehaviorCollection.Behaviors>
<local:BehaviorBinding Event="MouseLeftButtonDown"
Action="{Binding DoSomething}"
CommandParameter="An Action on MouseLeftButtonDown"/>
<local:BehaviorBinding Event="MouseRightButtonDown"
Command="{Binding SomeCommand}"
CommandParameter="A Command on MouseRightButtonDown"/>
</local:CommandBehaviorCollection.Behaviors>
<TextBlock Text="MouseDown on this border to execute the command"/>
</Border>
I want to know why we should use MVVM to implement Silverlight app. What're it's advantages?
We don't do Unit Test for ViewModel, so I want other reasons.
Below are my questions about some advantages people usually say:
1.Loosely Coupled : When we use MVVM , a view rely on ViewModel but not a view, why it's loosely coupled?
2.If I provide public methods in a code-behind, they can also provide reusability.
Well, the unit-testability of the view-model is a significant advantage, so you'll miss out on that benefit. Regarding the other two:
Loosely coupled
Yes, the view does rely on the view-model. They have to be connected in some way to accomplish the function of the application. As a result, they cannot be uncoupled. The only choices are tightly-coupled or loosely-coupled or somewhere in between. With MVVM your view-model interacts with your view in a very limited way: basically just objects, properties and commands. Compare this to doing everything in the code-behind where the view and its control are essentially inseparable.
Re-use
If any code in your code-behind is re-usable enough to merit being public, it can be taken out of the code-behind and put into a general-purpose class. The problem is that what's left after that is not reusable.
If you don't want to go into the MVVM deep dive, then you can get some of the benefits of MVVM by focusing on databinding. After you learn the benefits of databinding, you can reconsider the other benefits of MVVM.
We don't do Unit Test for ViewModel,
With MVVM, it isn't just about unit testing ViewModel. Ideally, your VM should be very thin and only have properties needed by view. So, it isn't really necessary to test the VM.
But, without a VM, how do you do your your feature/functional testing across layers? In Silverlight, to facilitate testing you should use commands, instead of writing code in code-behind files. This allows you to simulate button click and other GUI events while unit testing. Using MVVM pattern along with commands, you can test all of C# code (not xaml), right up to UI (Converter, VMs, etc).
If I provide public methods in a
code-behind, they can also provide
reusability.
Not going into details of how that is a bad design, I want to ask you, How does that provide reusablity? If you create a user control, then the code-behind class is a control? You want to create instances of your control and use them? This is like saying that why do we need member methods, we can just create public static methods and access them. I have a strong opinion that if we don't want to use the automatic binding provided by WPF/Silverlight, then it is better NOT to use these technologies. And to exploit the full capabilities of binding, MVVM is essential.
why it's loosely coupled?
VM is very much part of your view. It is not decoupled from the view. As I have said, your VM should be as thin as possible with only public properties needed by your view. Your business logic will be decoupled from your view (and VM).
I think this is one of the best resources available, in case you want to use and contrast the usage of MVVM vs. ANY other pattern or no pattern.
http://karlshifflett.wordpress.com/2010/11/07/in-the-box-ndash-mvvm-training/
I can answer how I use MVVM pattern.
MVVM is better in the following scenarios:
1 If several controls are bound with a single property.
MVVM:
<TextBlock x:Name="text1" Visibility="{Binding IsSomePropertyTrue, Converter={StaticResource VisibilityConverter}"/>
<TextBlock x:Name="text2" Visibility="{Binding IsSomePropertyTrue, Converter={StaticResource VisibilityConverter}"/>
I can quickly add a similar control or remove an existing control.
Compare with code-behind:
public string IsSomePropertyTrue
{
set
{
//...
text1.Visibility = value;
text2.Visibility = value;
}
}
2 Instead of a multi-converter
public Brush StateColor
{
get
{
if (this.State == State.Edited && this.IsPriority)
return new SolidColorBrush(Color.FromArgb(255, 0, 255, 0));
//...
}
}
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Background="{Binding StateColor}" Text="{Binding State}"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
3 As an item model in controls like ListBox or DataGrid. For example, if I want to create a list of items with a remove button near each item, I will create a ItemView control and a ItemViewModel class.
<ItemsControl ItemsSource="{Binding SomeItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<view:ItemView DataContext="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
4 Copying a data from one view to another:
public JournalEntryViewModel(SalesOrderViewModel vm) {}
5 ViewModel can inherit CLR-classes and implement interfaces (INotifyPropertyChanged or INotifyDataErrorInfo).
Also I use MVVM for replacing events with commands or properties. And use of ViewModels forces to call properties by intelligible names.
I was an early adopter for WPF and I can tell you what made me choose MVVM (and this more or less applies to Silverlight as well). For the project I was working on, I had to create a screen that allowed users to subscribe to notifications within the system. This was a 3 step process:
The user had to search for the item they wanted to be notified about
They had to select the item and fill out additional options regarding the subscription
The system had to provide a summary and allow the user to confirm or edit the subscription.
After implementing the functionality the first time (without MVVM), I was told that we need to exclude from the search items that were already subscribed to by the user.
After making that fix, I was informed that we needed to give the user a live preview of the subscription based on options.
By then I started noticing that some of these changes could be extracted and made easier if I didn't have to deal with manipulating the UI as I changed the logic. I had never intentionally followed MVVM but I realized that the abstraction that I made closely matched the MVVM pattern.
So this is why I recommend the pattern. It simplifies the task of changing the logic that drives the UI by separating it from the UI itself. I also would recommend that you hold off implementing it until you need it. There is a cost to using MVVM but it is amortized over the cost of changing the UI logic.
Without MVVM, your Silverlight app code very soon will turn into unmanageable mess
What is also interesting in MVVM is dynamic automatic binding.
Imagine, that your view model has properties like this: bool IsFirstNameVisible, bool IsFirstNameEnabled, string FirstName, double FirstNameWidth etc.
In your XAML file, you define TextBox with x:Name = "FirstName" and call your dynamic MVVM-binder. It inspects your view model class via reflection, looks what properties you have defined and binds them dynamically to similar properties of control with the same name, applying value converters if needed.
In this case, your get very clean XAML, without kilometer-long data-binding expressions and converters.
That is what my MVVM library does.
Separation of Conerns people. Separation of Concerns.
Forget unit testing (I love it; but that's not the thing here). Forget reusability (do you really re-use view models? No, let's be real here).
It's about Separation of Concerns and putting code and logic where it belongs. The whole idea is maintainability; being able to make changes to the code as it evolves over time without breaking other stuff and without turning the whole thing into a big pile of spaghetti.
MVVM, done properly, allows your code to be separated into logical portions that make sense and allow for reasy refactoring and change as the app's requirements change. It's easier to find where something is when you need to make a change. Trying writing any halfway complex application and then leaving it alone for a month, then coming back to it and trying to make significant changes. A properly structured application with judicious use of MVVM is way easier to grok after a layoff, and it's way easier to make changes.
In learning WPF, I've been reading scads of books and web sites. One thing that seems to keep evading me is how we are supposed to properly wire up RoutedCommands. In one article, the author pointed out that the codebehind for your XAML files is supposed to contain nothing more than the call to InitializeComponent. I can get behind that. It makes the XAML file nothing more than a presentation document, and satisifies my unholy craving for separation of concerns.
On the other hand, every sample I've seen that addresses double-click events seems to want you to write code. It was my understanding that we wanted to get away from having repetitive code in the codebehind files (and, again, I'm all for that), so it seems to me that that's not the right way to do it. The same is true of menu commands, toolbar button clicks, and so forth.
Imagine, for instance, that I have a command to open a document. That command has to present the Open dialog, then open the document and cache it in the application state. (This application only allows you to work on one document at a time.) The user can invoke this command by either:
Choosing File->Open from the menu.
Typing Ctrl+O.
Clicking the Open button on the toolbar.
If I trust most of the sources on the Web, I have to write at least two Click event handlers that then invoke the command, polluting the codebehind file. That seems, to me, to defeat the purpose of having the Commands. I thought that I read somewhere that there was a way to bind the command to these things declaratively in XAML and it would do it for you, even disabling the command if it couldn't execute. But now I can't seem to find it, nor a decent example of how to do it.
Could someone please explain this to me? It's all starting to look like voodoo and shrapnel at this point.
The usual way to avoid codebehind with commands is to avoid RoutedCommands. In the various variations on the MVVM (Model-View-ViewModel) theme, people tend to use custom implementations of ICommand. They write a ViewModel class that is placed in the DataContext of the UI. This ViewModel exposes properties of type ICommand, and those command properties are connected to menu items, buttons and so on through data binding. (And it's usually just the one implementation of ICommand used over and over again - search the web for either RelayCommand or DelegateCommand or DelegatingCommand, and you'll see the pattern - it's basically ICommand as a wrapper around a delegate, with optional support for enabled/disabled.)
In this idiom, you almost never use the built-in commands like ApplicationCommands.Open. The only real use for those things is if you want focus-sensitive commands to be handled intrinsically by controls. E.g., the TextBox has built in command handling for Edit, Copy, Paste, and so on. This avoids the codebehind issue because it's a full custom control, and custom controls don't really have codebehind as such - they're all code. (The Xaml is actually in a completely separate object, the Template, and isn't really part of the control.) And in any case, it's not your code - you have a control that already knows how to support the command, so you can keep entirely within the Xaml here.
Command routing is interesting in that particular scenario because it lets you put one set of menu items associated with the various editing controls, and the routing system figures out which textbox (or whatever) will handle the command based on where the focus is. If that's not what you want, command routing probably isn't much use to you.
However, there's a bigger issue here of what to do when you find that you really do have to put code in the codebehind. Commands usually aren't an example of that scenario if you use custom ICommand implementations (although there's the odd exception), but the slightly more interesting user input events are. You mention double click, but also, if you're doing any kind of unusual interactivity you tend to want things like mouse up/down and so on.
In this case, the usual approach is to bite the bullet and put code in the codebehind, but you try to keep it to one line per event handler. Basically, your codebehind just calls into the relevant method on the viewmodel, and that's what really handles the event.
The lovely thing about that is it makes it really easy to write automated tests. Want to simulate the mouse entering a particular part of your UI? No need to mess around with unit test UI automation frameworks - just call the relevant method directly!
Commanding in WPF is quite cumbersome, but it does solve the problem of updating IsEnabled for you. Here's the canonical example. Step 1 is optional because there are a lot of built-in common commands to reduce the amount of boiler-plate.
Step 1. (Optional) Create your command in a static class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
namespace WpfApplication1
{
public static class Commands
{
public static RoutedCommand WibbleCommand = new RoutedUICommand
(
"Wibble",
"Wibble",
typeof(Commands),
new InputGestureCollection()
{
new KeyGesture(Key.O, ModifierKeys.Control)
}
);
}
}
Step 2: Declare command bindings in the xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding
Command="{x:Static local:Commands.WibbleCommand}"
Executed="WibbleCommandExecuted"
CanExecute="WibbleCommandCanExecute"
/>
</Window.CommandBindings>
Step 3: Wire up your controls (menuitems, buttons etc)
The long binding here is to rectify the fact that Button by default won't use the command text.
<Button Command="{x:Static local:Commands.WibbleCommand}" Width="200" Height="80">
<TextBlock Text="{Binding Path=Command.Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}">
</TextBlock>
</Button>
Step 4: Implement handlers for Execute and CanExecute in codebehind
Careful with CanExecute! This will be called quite often, so try not to do anything expensive here.
private void WibbleCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Wibbled!");
}
private void WibbleCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = DateTime.Now.Minute % 2 == 0;
}
Does anybody have an idea how to change screens (views) in a MVVM View-First-Approach (The view instantiates the ViewModel:
DataContext="{Binding Source={StaticResource VMLocator},
Path=Find[EntranceViewModel]}"
)
For example:
In my MainWindow (Shell) I show a entrance view with a Button "GoToBeach".
<Window>
<DockPanel>
<TextBox DockPanel.Dock="Top" Text="{Binding Title}" />
<view.EntranceView DockPanel.Dock="Top" />
</DockPanel>
</Window>
When the button is clicked I want to get rid of the "EntranceView" and show the "BeachView".
I am really curious if somebody knows a way to keep the View-First Approach and change the screen (view) to the "BeachView".
I know there are several ways to implement it in a ViewModel-First Approach, but that is not the question.
Perhabs I missed something in my mvvm investigation and can't see the wood for the trees... otherwise i am
hoping for a inspiring discussion.
One possibility would be to have all views in the (MainWindow(Shell) and using Triggers for their visibility. But having a lot of different screens (views) all declared in the MainWindow doesnt feel right for me...
This question came up while reading this nice way of using MEF with MVVM I found on John Papas Blog: Simple ViewModel Locator for MVVM: The Patients Have Left the Asylum . But as nice as this marriage of view and viewmodel is, it seems like there is no way to change screens that satisfies me. :)
So in my opinion if you have a lot of screens(views) you better use a ViewModel-First-Approach...
This looks like it might help:
Creating a ViewModel : do it before or after model data is available?
Failing that, how about creating the ViewModel once only at startup, and assigning it to each View window as it's created (rather than creating a new ViewModel each time). Then just close the first View and open up a new View as required, reassigning the single ViewModel instance.
You may want to look at Prism (i.e. the composite application library). Prism facilitates navigation between views via the region manager. This might be overkill for your application and can take a while to get your head around. Prism also allows you to develop using the MVVM pattern as well.
You can find more information about prism and prism navigation in the Prism documentation.