WPF Commands - Doing it with no code-behind - wpf

I'm building a simple data entry app in WPF form using the MVVM pattern. Each form has a presenter object that exposes all the data etc. I'd like to use WPF Commands for enabling and disabling Edit/Save/Delete buttons and menu options.
My problem is that this approach seems to require me to add lots of code to the code-behind. I'm trying to keep my presentation layer as thin as possible so I'd much rather this code/logic was inside my presenter (or ViewModel) class rather than in code-behind. Can anyone suggest a way to achieve the same thing without code-behind?
My XAML looks a bit like this:
<Window.CommandBindings>
<CommandBinding
Command="ApplicationCommands.Save"
CanExecute="CommandBinding_CanExecute"
Executed="CommandBinding_Executed"
/>
</Window.CommandBindings>
and my code-behind looks a bit like this:
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = (
_presenter.SelectedStore != null &&
_presenter.SelectedStore.IsValid);
}

The Model-View-ViewModel (MVVM) design pattern aims at achieving exactly that goal, and Josh Smith's excellent article explains how to apply it.
For commands you can use the RelayCommand class described in the article.
Since you already have a presenter object, you can let that class expose an ICommand property that implements the desired logic, and then bind the XAML to that command. It's all explained in the article.

If you're specifically looking at trying to bind a command in the ViewModel to one of the application commands in XAML, you have to build the infrastructure to do so yourself. I walk though doing that in this answer which then allows you to do something like this:
<local:RoutedCommandHandlers.Commands>
<local:RoutedCommandHandler RoutedCommand="ApplicationCommands.Save"
Command="{Binding TheSaveCommand}" />
</local:RoutedCommandHandlers.Commands>

Related

ViewModel Handling Events

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>

wpf button click

I Have a WPF app with 5 pages. On my main window I have 5 buttons. What I would like to do is click button 1 to open page 1 in a frame on the main window. I dont want to use a navagation window. Should I use some kind of binding? I would like to use xmal, the less code the better. Thanks in advance I'm in the learning stages!
You could set your buttons' Click event handlers to call Frame.Navigate(Uri) with their respective page.
In XAML:
<Frame Name="myFrame"/>
<Button Name="buttonPage1" Click="OnClickPage1">
Page1
</Button>
Then in the code behind:
void OnClickPage1(object sender, RoutedEventArgs e)
{
myFrame.Navigate(new Uri("page1"));
}
I assume that the logical follow-on from your comments is that pressing button 2 will open page 2 etc.
My recommendation, and this goes for all WPF development, is to adopt MVVM. It will give you a lot more flexibility and testability.
To implement your problem in MVVM:
Create ViewModels for each of your views, and one for your Main window
Each ViewModel becomes the DataContext for its respective View.
In the MainWindowViewModel implement 5 ICommand properties and bind the Command property on the button to each corresponding ICommand properties on the MainWindowViewModel.
On the main window, I am not sure if you are implementing a Frame control, but I would suggest using a ContentControl, bind the Content property on the control to some property of type Object on the MainWindowViewModel.
In the execution of each of the ICommand objects, you would set the content property on the MainWindowViewModel to the matching ViewModel for that button.
In the MainWindowView.xaml you would need to implement a series of DataTemplates which map the ViewModel to a View:
<DataTemplate DataType="{x:Type Page1ViewModel}">
<AdornerDecorator>
<views:Page1View DataContext="{Binding}"/>
</AdornerDecorator>
</DataTemplate>
I would suggest that you look at using one of the many MVVM frameworks available.
MVVMFoundation - light weight, bare minimum implementation
MVVMLight - heavier framework
Caliburn - seems to have a lot of additional functionality
Implementing a full framework might seem like a lot of extra work but it will be worth it in the long run, more testable, more maintainable.

WPF Architecture Confusion RE: Routed Commands, Events, and Gestures

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

Binding Commands Without Using the DataContext [silverlight+prism]

Hello I have a problem with binding commands to button inside datagrid.
Here should be explanation but it doesn't explain everything.
http://msdn.microsoft.com/en-us/library/dd458928.aspx
What should be in classes in namespace Infrastructure?
Can somebody show me a really basic sample of using this?
not just parts of the code...
The Prism Commanding QuickStart - included with the Prism drop should provide the simple code example you are looking for.
All data-bindings go against the current DataContext unless specified otherwise. The DataContext is inherited down the tree of controls unless a control specifically picks a DataContext.
For example your Button might look like this and would look for the SaveCommand on whatever the DataContext has:
<Button Command="{Binding SaveCommand} />
Your button could also look like this if you wanted to bind to a command exposed on your classes code-behind:
<UserControl x:Name="UserControl">
...
<Button Command="{Binding SaveCommand, ElementName=UserControl}"
...
</UserControl>
Using DelegateCommand is just a way of implementing the ICommand you bind to and that should be visibile in the Prism QuickStart.

MVVM What is the way of updating a UI after a command?

I'm learning MVVM through a project and I got stuck on something simple.
I have a Button that updates a ListView. I have a command in the ViewModel that make the right things but I want to select the new row and get the focus on a TextBox after I click the Button.
The question is: How do I update my UI after executing a command?
If I need to change my windows Title when an operation have been made, I use a property on the ViewModel that is binded to the Window's title and it's changed when I need it but, I don't know how to get focus on a control when a command has been executed.
Thank you.
To select the new row, add a new property to your ViewModel ("SelectedItem" for instance), and bind the ListView's SelectedItem property to it :
<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">...
In the ViewModel, you just have to assign the new item to the SelectedItem property
To focus the TextBox, Mike's idea seems a good one
You could make an attached behavior. I'd suggest using the new Blend behavior framework, ie TriggerAction that contained this custom logic.
For your attached behavior you put on the button, give it a DP for an ICommand and maybe a DP of a ListView type.
On the "protected override void Invoke(object parameter)" of your TriggerAction, execute your ICommand, then you have reference to your ListView. Here you can do your custom code on it, like setting focus.
Your XAML may look something like this:
<Button>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<Behaviors:CustomBehavior Command="CommandName" ListView="{Binding ElementName=myListView}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Button/>
I suggest looking at Mike Brown's ExecuteCommandAction behavior (download here), it's about almost 1/2 of what you need.
What about setting focus to the control in the code behind: textBox.Focus()
I consider everything you mention in your question to be GUI logic so I would add a Click event to the button to handle stuff that needs to happend in the GUI.
Hope this helps.
I think you need to use the Mediator pattern. Please see this:
Josh Smith's Mediator Prototype for WPF Apps
This is generally used in communicating with the View from the View-Model. Hope this helps.
In your case you need some way that the ViewModel notifies the View that it should set the focus on a specific control.
This could be done with an IView interface. The view implements this interface and the ViewModel can call a method of the View over this interface. This way you have still the View and ViewModel decoupled of each other.
How this can be done is shown here:
WPF Application Framework (WAF)
http://waf.codeplex.com

Resources