WPF MVVM and Unit Testing - wpf

I have been working on a WPF application and I am using the ModelViewViewModel design pattern. I have a number of events that come out of the view, that result in ViewModel activity.
What is the resonable way to get these events raised from a UnitTest? For example, I want to simulate the drop event. I don't really want to build a stub view, just to raise the event.
Any suggestions welcome.
Thanks.

According to the MVVM pattern:
The View knows about the ViewModel - it will have a reference to it either as a concrete instance or an interface
The ViewModel should not know about the view at all.
If you need to handle events, then there are two ways which I know of to do it:
1: Expose a command in your viewmodel, and use databinding to trigger it. This is my preferred way, eg:
class MyViewModel
{
public ICommand ClickCommand { get; set; }
}
<Button Command="{Binding Path=ClickCommand}" />
If you do this then you can test the command by simply calling myViewModel.ClickCommand.Execute manually.
2: Expose a function in the viewmodel, and write the absolute minimum in the .xaml.cs file to handle the event and call the function, eg:
class MyViewModel
{
public void HandleClick(){ }
}
<Button Click="MyClickHandler">
//.xaml.cs file
public void MyClickHandler( Object sender, EventArgs e ) {
m_viewModel.HandleClick()
}
If you do this, then you can test by simply calling myViewModel.HandleClick manually. You shouldn't need to bother with unit testing the MyClickHandler code as it's only 1 line!

It sounds like you have an event handler for the drop event directly in your ViewModel class. Would it make more sense to have the handler in your UI layer, which in turn will call a function in your ViewModel? This way, your unit test could just call the function (simulating a drag and drop operation, as far as the ViewModel is concerned).
Plus, it would better separate your ViewModel from your UI code.

Don't raise an event, just call the handlers (which means they should be public, and probably take less event handler centric arguments). Check out how this is done in Caliburn (http://www.codeplex.com/caliburn) using "Actions".

Why don't you use a mocking framework, such as Moq? Check out their quick start, it has a sample on mocking events. The url is: http://code.google.com/p/moq/wiki/QuickStart

Related

How can I trigger some code to run in the view from the view model?

What is the best way for the view model to "ask" the view to do something, (e.g. manipulate on of the controls)? I don't think that the view model sending events violates MVVM as after all the INotifyPropertyChanged interface is an example of view models sending events to views.
I realize that having code behind in the view is not considered ideal from a MVVM perspective, so I could use an attached behavior to manipulate a particular control for example but the problem remains - how do I ask the attached behavior to do something from my view model?
I could have Boolean dependency property on my view with property changed event handler which runs the code I need to run. I could then bind this property to a property on my view model and then toggle the value of this property whenever I want to trigger the code to run. However this seems like a hack.
I could have an event on the view model and then explicitly attach this event to an event handler in the view in code but this seems anti MVVM - I should be able to achieve the connection using binding.
This must be a fairly common scenario, are there any standard solutions?
You could for example use an event aggregator or a messenger to send an event or message from the view model that the view handles in a loosely coupled way. Both the view and the view model know only about the event aggregator but they don't know anything about each other. Please refer to this blog post for more information about the concept.
Another common approach is to implement an interface in the view and inject the view model with this interface, e.g.:
public interface IDoSomething
{
void DoSomething();
}
public partial class Window1 : Window, IDoSomething
{
public Window1()
{
InitializeComponent();
DataContext = new ViewModel(this);
}
public void DoSomething()
{
//do something...
}
}
public class ViewModel
{
public ViewModel(IDoSomething doSomething)
{
//...
}
}
This doesn't break the MVVM pattern as the view model knows about and is dependant only on an interface.

A Controller for MVVM

I'm working on a WPF project that's a mishmash of code-behind xaml/xaml.cs and a few not-quite ViewModels as well.
(Disclaimer: Until recently I've had very little in the way of WPF experience. I can design and lay-out a Window or UserControl fairly proficiently, and I think I get the hang of separating an MVVM ViewModel from the View and doing binding wire-ups, but that's the limit of my experience with WPF at present.)
I've been tasked with adding some new features to the program, such that it looks like converting it to use MVVM properly first is going to be necessary.
I'll demonstrate a specific problem I'm facing:
There is a View called SettingsWindow.xaml that I'm working with. It's a set of textboxes, labels and whatnot. I've stripped-out all of the View data into a ViewModel class which resembles something like this:
class SettingsViewModel : ViewModelBase {
private String _outputDirectory;
public String OutputDirectory {
get { return _outputDirectory; }
set { SetValue( () => this.OutputDirectory, ref _outputDirectory, value) ); }
}
// `SetValue` calls `PropertyChanged` and does other common-tasks.
// Repeat for other properties, like "Int32 Timeout" and "Color FontColor"
}
In the original ViewModel class there were 2 methods: ReadFromRegistry and SaveToRegistry. The ReadFromRegistry method was called by the ViewModel's constructor, and the SaveToRegistry method was called by MainWindow.xaml.cs's code-behind like so:
private void Settings_Click(Object sender, RoutedEventArgs e) {
SettingsViewModel model = new SettingsViewModel(); // loads from registry via constructor
SettingsWindow window = new SettingsWindow();
window.Owner = this;
window.DataContext = model;
if( dialog.ShowDialog() == true ) {
model.SaveToRegistry();
}
}
...but this seems wrong to me. I thought a ViewModel should consist only of an observable data bag for binding purposes, it should not be responsible for self-population or persistence, which is the responsibility of the controller or some other orchestrator.
I've done a few days' worth of reading about MVVM, and none of the articles I've read mention a controller or where the logic for opening child-windows or saving state should go. I've seen some articles that do put that code in the ViewModels, others continue to use code-behind for this, others abstract away everything and use IService-based solutions, which is OTT for me.
Given this is a conversion project where I'll convert each Window/View individually over-time I can't really overhaul it, but where can I go from here? What does a Controller in MVVM look-like, exactly? (My apologies for the vague terminology, it's 3am :) ).
My aim with the refactoring is to separate concerns; testability is not an objective nor would it be implemented.
I personally disagree with putting much in my ViewModels beyond the stuff that is pertinent to the View (it is, after all, a model of a View!)
So I use a Controller paradigm whereby when the View tells the ViewModel to perform some action (via a Command usually) and the ViewModel uses a Command class to perfrom actions, such as saving the data, instantiating new View/Viewmodel pairs etc.
I also actually separate my ViewModel and ViewData (the ViewModel 'contains' the ViewData) so the ViewData is puirely dealing with the data, the ViewModel with some logic and command handling etc.
I wrote about it here
What you need is called Commanding in WPF.
Basically you bind Button.Command to a ICommand property in your ViewModel and when Button is clicked you get a notification in ViewModel without using code behind and casing DataContext or whathever hacks you tried.
http://msdn.microsoft.com/en-us/library/ms752308.aspx

Caliburn Micro subscribe to onpropertychanged event from view code behind

I'm working on a silverlight project that has a file viewer. This file viewer does not have a Source property or other property that accepts a stream. It does have a LoadDocument(Stream file) method. Since the file will be loaded asynchronously I need to "Notify" the view that the buffer is available and then let the View call the LoadDocument method.
In MVVMLight I could do this with the "Messenger" functionality. I see the EventAggregator but everything I see has the communications going the other way. I feel like this should be really easy to do but I just don't see it.
Is there a way in the Views constructor to bind a method to a property of the ViewModel? It seems to be this is the same functionality that is done in xaml I just want to do it in the code behind.
Thanks
dbl
Not sure by the post but it sounds like you want to bind an event from a control to a method on your view
In that case:
<SomeControl cal:Message.Attach="[Event SomeEvent] = [Action SomeMethod($eventArgs)]" />
If it's the other way round you can either use the event aggregator (the view can subscribe to events... why not, it's decoupled still...)
VM:
SomeEventAggregator.Publish(new SomeMessageInstanceThatTheViewWillSubscribeTo());
View:
class SomeView : UserControl, IHandle<SomeMessageInstanceThatTheViewWillSubscribeTo>
// dont forget to...
SomeEventAggregator.Subscribe(this);
Alternatively - implement an interface on the view
class SomeView : UserControl, IAcceptSomeNotificationMessage
{
public void Notify() { // blah
}
}
VM:
class SomeViewModel : Screen // whatever
{
void SomeMethod()
{
// The VM should be IViewAware so will implement GetView()
var view = GetView();
if(view is IAcceptSomeNotificationMessage)
(view as IAcceptSomeNotificationMessage).Notify();
}
}
Pick one of the above - I'm sure there are more ways. I usually use an event aggregator - of course it depends on how much IoC you are using and how decoupled everything is.

WPF MVVM Problems with View

I want to use WPF with MVVM pattern in my project, but i am confused about some points regarding MVVM pattern. Please help me to clarify these points.
I am using DataTemplate for ViewModel, but i want specific control to be keyboard focused.
How can i focus specific control after ICommand Executed.
How can i move focus to not validated control.
Is there any way to separate DataTemplate depending on ViewModel property value.
How can i validate all controls before ICommand
Is there any other better approach to ask any confirmation from ViewModel with MessageBox
Regards,
Mitan
I highly suggest you have a look at caliburn (or caliburn.micro) which exposes different UImanager interfaces so your viewmodel can do such things without losing unit testability.
To set the foucs on control use codebehind. MVVM doesn't say don't not use codebehind.
Write a method on code behind to set the focus and call this method from view model.
Example
public interface IView
{
void setFoucs();
}
//Code Behind
public class MyWindow : Window, IView
{
public void SetFoucs()
{
MyControl.Focus();
}
}
public class ViewModel
{
public IView _view { get; set; }
public ViewModel(IView view)
{
_view = view;
}
public void SomeMethod()
{
_view.SetFocus();
}
}
For question no 4 - I think your are looking to selecte specific datatemplate based on your some logic. To achieve this use DataTemplateSelector class.
http://www.switchonthecode.com/tutorials/wpf-tutorial-how-to-use-a-datatemplateselector
Question 1:
Not clear what you mean/want. Generally the TabIndex controls the focus flow in your application, with silverlight it is however not as easy to configure as in windows forms. Silverlight also does a good job at setting the tab sequence automatically.
However, you should note that all controls inheriting from Control receive, by default, the focus. This incudes some controls that may be used as a container for other controls (e.g. ContentControl). This behaviour might lead to some unwanted effects. Use the IsTabStop property to remove these controls from the tab order.
Question 2:
Well, it depends on how decoupled you want your application (the more decoupled the better). #pchajer's approach is one way of doing it, however it couples the view to the view model and this - although abstracted via an interface - is IMHO not a good idea for the following reasons:
Usually the view model is pulled from a locator in order to allow for blendability. Now if I have to use code behind to pass the View to the ViewModel this might break it. Better would be if it could be injected into the ViewModel via a constructor parameter and this would then break the locator.
The code becomes less testable as it now depends on the view. To make it testable you need to inject an implementaion of IView into the ViewModel, and this breaks the locator again.
Therefore, I would advise you to use Messaging to send a message to your view once the Command is complete. Then you can set the focus in the message handler. However, be aware that your might have to use the Dispatcher as the message handler could run in a separate thread.
Question 3:
You could capture the BindingValidationError on the control and then set the focus. Again be aware of possible threading issues.
Question 4:
Not sure, but if you mean that you want to use different DataTemplates based on whether a property has a certain value or not a TemplateSelector might help you. See http://www.switchonthecode.com/tutorials/wpf-tutorial-how-to-use-a-datatemplateselector.
Question 5:
The controls are validated when the property change event is fired, usually on the lost focus event. Your Model/ViewModel can implement IDataError to do the validation, and your can access this value from the CanExecute method associated with your command. However, you should try to keep the code in the CanExecute method as quick as possible as this method is called quite frequently.
Question 6:
You can implement your own Window that provides a custom layout. However, using the message box is a lot simpler. Again you should think of using messaging or a dialog service (e.g. http://blog.roboblob.com/2010/01/19/modal-dialogs-with-mvvm-and-silverlight-4/) to decouple your View and ViewModel. In fact there is even a DialogMessage in MVVMLight.

Calling a Method of a UserControl in MVVM

I'm having an issue with calling a method on a UserControl. Hear me out:
I have a UserControl someControl in SomeView.xaml
SomeView.xaml's DataContext is SomeViewModel.cs
I want to be able to call someControl.DoStuff() somehow, somewhere.
DoStuff is not UI specific (I could have just called DoStuff from the code-behind of SomeView.Xaml.Cs if it was UI specific, but in this case, it may not be.)
Any ideas?
Thanks!
You're probably not going to like the answer, but your ViewModel should have no knowledge of your UI. If you have a non-UI method on your UserControl, it's probably in the wrong place.
The only thing I could think of is that you may want to implement some type of messaging (like they have in MVVM Light) that could trigger the execution.
It's either that, or rethink how you've architected your code.
One the SO answer to Achive this by decouples the ViewModel's knowledge about View is by using the Action delegates answered by Mert here
Pasted his code here, if the link breaks by any chance.
class MyCodeBehind
{
public MyCodeBehind()
{
Action action = new Action(()=> this.SomeMethodIWantToCall());
var myVM = new MyVM(action); // This is your ViewModel
this.DataContext = myVM;
}
private void SomeMethodIWantToCall(){...}
}
class MyVM
{
private Action action;
public MyVM(Action someAction)
{
this.action = someAction;
}
private void SomeMethodInVM()
{
this.action(); // Calls the method SomeMethodIWantToCall() in your code behind
}
}
It sounds like you want DoStuff to happen in response to some data or logic in your VM, in which case the cleanest method would probably be to use an event originating in your VM and handled by DoStuff. If the trigger is more like a state change you could also bind the appropriate VM data to a new Dependency Property on your UserControl and call DoStuff from the DP's change handler.
Maybe your UserControl should really be a View, which then should have a ViewModel, which would contain the DoStuff() method. SomeViewModel will have instantiated (are at leased casused to be instantiated) SomeControlViewModel, and so be able to call a method on it.
If you have View-first approach (and your VM is instantiated as Resource in XAML) you may use some normal events to connect your control DoStuff method with some event on VM (on Loaded event).
If the method DoStuff(); does some UI specific logic then the method is in the right place. When not then it should be in another object (e.g. SomeViewModel).
SomeViewModel is allowed to call a method on SomeView when it is separated via an interface. How this can be accomplished is shown by the WPF Application Framework (WAF).
In MVVM design, the idea is generally not to have ANY code in your UserControl (the xaml.cs file) (in an ideal world). All interaction between the UI and the ViewModel should be handled via Commands and Bindings...so why do you need DoStuff in your user control?
You might have something like
<Button Command="{Binding myCommandOnTheDataContextViewModel}" Content="{Binding somePropertyOnTheViewModel}" />

Resources