Implement interface with WPF MVVM pattern - c#

I wanna implement an interface(Add behavior) for set of WPF usercontrols.
I'm using MVVM design pattern.
Where I should implement the interface? in usercontrol code behind or in View model class?
Ex:
My Interface is
interface IWizard
{
event RoutedEventHandler MoveNext;
event RoutedEventHandler MoveBack;
event RoutedEventHandler Cancelled;
bool IsLast;
bool IsFirst;
}
Now in other place I wanna access user controls which are implemented this interface as this.
((IWizard)userControl).MoveNext += ...
((IWizard)userControl).MoveBack += ...
((IWizard)userControl).IsLast = true;
etc..
Implement in UserControl Code behind
I can't acess the interface's properties/methods directly in view model. I have to link them manually. right ?
PS: In this example I wanna Bind(TwoWay Bind) IsLast Property with a visibility of a button.
Implement in View model class
I can't access the usercontrol as a Interface object.
ex: ((IWizard)userControl).MoveNext += ...
What is the best practice on Implementing an Interface on Usercontrol with MVVM design Pattern?

You should implement this interface in UserControl because it is directly related to UserControl, it has nothing to do with ViewModel. View Model is for business logic and interaction between View and Model. Events which occurs on UI/View should not be doing anything on ViewModel directly.
I know you won't be able to access properties directly in view model but that's what MVVM is for. Use the bindings and commands to bind properties and methods from Control to your ViewModel

In perfect-world MVVM, ViewModel has no knowledge whatsoever about View. Whether View implements any interface at all is irrelevant from ViewModel's point of view.
In your scenario, what I think is more important is who will respond to MoveNext, MoveBack and Canceled events. Most likely, that would be ViewModel. What that means you probably could use methods such as WizardMoved(object sender, EventArgs e) in those ViewModels. Look what we've done here - ViewModel needs to have kind of indirect knowledge about View. That is not a good sign.
Perhaps instead, you could approach problem differently. Maybe what you need is IWizardMovement interface that will define methods to handle wizard moving events - and this interface will be implemented by ViewModels. So that when you pass ViewModel to View, it can easily subscribe ViewModel's handlers to its own events (note that not it doesn't really matter what interface View implements).
public interface IWizardMovementViewModel
{
void WizardMovedNext(object sender, EventArgs e);
void WizardMovedBack(object sender, EventArgs e);
void WizardMoveCanceled(object sender, EventArgs e);
}
Now, since in MVVM View knows about ViewModel (and never the other way around), you can easily utilize this knowledge:
// Wizard user control constructor
public Wizard(IWizardMovementViewModel viewModel)
{
MoveNext += viewModel.WizardMovedNext;
MoveBack += viewModel.WizardMovedBack;
Canceled += viewModel.WizardMoveCanceled;
}
ViewModel is separated from View for good now, and how your View looks like is not important anymore (as it should never been in first place).

First of all, your view-model shouldn't have a field called "userControl".
When you design an MVVM application you should think in terms of layers. The Model layer should be usable by itself. The View-Model layer shoul be usable with the Models and Services. The View is what combines everything together.
But what about navigation?
Rather than giving your view-model direct access to the user control, you should only give it access to the abstract notion of navigation. In WPF that means NavigationWindow.NavigationService or Frame.NavigationService.
You can see an example of this in NavigationViewModel class in Granite.Xaml (http://granite.codeplex.com/SourceControl/changeset/view/85060#2109525). Since it takes an abstract interface (INavigator in my case, IWizard in yours) you can still test the view-model in isolation using simple mocking techniques.

Add a IsLast property to the ViewModel, make sure it raises NotifyPropertyChanged correctly.
Bind the Visibility of the Button to the IsLast property using a ValueConverter that converts a boolean into a Visability and back.
Done.

Related

Consultation about the best design for MVVM

little question. I'm progrraming in MVVM design pattern (C#).
the View is an Excel add-in, and I want to run from the View_Model a method that found in the View. I thought about 2 ways:
Hold in the View Model a pointer to the View (the pointer type is an interface that the View and the View_Model inherit from, otherwise I would get a circular independence because the View hold the View_Model and the View_Model hold the View), and then run the method directly from him.
Create an event in the View_Model and sign the method in the View to that event in the View_Model pointer which I already have in the View, and raise the event when I want to run this method.
Somehow, way number 2 feel little like screaming in the street to only one man instead off go straight and talk to him normally. On the other hand, the advantage in way number 2, is that in the future if I would have other method that relate to this operation I could just sign them to that event and not call them specially.
what would you do?
Method 1 breaks the MVVM principle since the view model should not know about the view. Your approach is a bit like the MVP design pattern.
I would say method 2 is the better approach, it's perfectly fine for the view to know about the view model. It also gives you the flexibility to do whatever you want when that event is raised, say for example, if you wanted to use a different view and call a different method.
Also, this kind of thing can be done using a good messaging framework. The view model publishes a message, the view subscribes to it. The mvvmlight frame work has a good implementation of this, but I am sure there are others too.
take an Interface, implement the view from it. And instantiate the viewmodel by passing this view.
lets say -
Interface
public interface IFooView
{
...
}
View
public Class FooView : IFooView
{
private FooViewModel _viewModel;
public FooView()
{
_viewModel = new FooViewModel(this);
}
}
ViewModel
public class FooViewModel
{
private FooView _view;
public FooViewModel(IFooView view)
{
_view = view;
}
}
Now, you can call the ViewModel from View, also View from ViewModel.

ViewModel calling a method of a user control (web browser)

I am trying to program in MVVM and I have the following use case:
A TextBox's text is bound to a property in the VM
A Button is command bound to a relay command
When the user presses the Button, the web browser's Navigate(url) method is called with the URL being the text in the TextBox
Above is the use case I want to create, but 1 and 2 is possible using the MVVM design pattern, but I could not find an adequate way to invoke the browser's Navigate() method. First of all, is it possible to call a method of a control from VM (please let me know if there is a way)? And in the above use case, what would be the appropriate way to structure the program if it is not possible?
Thanks
You could do the following:
Add a property MyUrl to your ViewModel
Bind MyUrl to your WebBrower's Source property
Make sure the property implements INotifyPropertyChanged. Then your Xaml:
<WebBrowser Source="{Binding MyUrl}" />
What if you REALLY wanted to call a UI method from the ViewModel?
If you ever do run into a situation where you absolutely need to call a method on a UI control for instance, you can hook up events on the ViewModel and then your UI registers to this event and does something UI specific...
VM code...
//... some VM logic
EpicNavigateEvent(url) // raise event, allowing UI to handle how
In your code-behind on your view (this is the part where some MVVM purests freak), you could register the event:
myVm.Navigate += doSomeNavigation;
...
public void doSomeNavigation(string url)
{
// call Navigate
}
I've successfully used this approach for applications where we have a single ViewModel layer and multiple technologies hooked up the views (WinForms, WPF and Asp.Net).
If you're looking for something more elegant, have a look at the User Interaction Patterns on MSDN.
The concept is the same though: Call something on the VM and the View is handles it appropriately.
Common scenarios for this type of approach is want to show a message to the user from the VM. Your VM should raise an event saying: ShowMyMessage("You're awesome"), then your UI is notified and handles it: MessageBox.Show(msg) or whatever.
As long as you stick to there rules you should be golden:
ViewModels should NOT be concerned about UI code
Views must ONLY handle the presentation of the data provided by your ViewModels.
Don't overcomplicate it. KISS...

How to call NavigationService from ViewModel

This is more complex than it sounds. I'm implementing MVVM pattern, which states a ViewModel cannot have a reference to it's View. That being said, I'm implementing Page navigation so that changes in views are done by using NavigationService in the View's code behind (let's say by pressing the "Next" button).
At some point in the program, we need to change Page using a voice command instead of a button (using speech recognition), and that logic is handled in the ViewModel (which doesn't have a reference to NavigationService).
So, without keeping a reference to thew View inside the ViewModel, how can I change page using NavigationService?
You could publish a "next page requested" message from within your view model using something like an event aggregator. Your view then subscribes to the message and handles it by using NavigationService to change the page. If you are using an MVVM framework most of them provide a way to publish / subscribe to messages out of the box.
In your Core (nonUI) project that containts your view models. Create a INavigationService interface:
public interface INavigation
{
void Navigate(IViewModel viewmodel);
void GoBack();
}
Then in your UI project, provide the implementation for that interface. You can get fancy with how you provide that implementation to the view model.
In the simple form you'd want to do something like:
public class MyViewModel
{
public MyViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
}
}
When the app starts up give the view model the implementation. At that point all your navigation can live in the view model. If you need to navigate from a view, execute a command on the view model and have it navigate.
Take a look at how MvvmLight does it:
INavigationService,
NavigationService

WPF: Close a Window from Model MVVM

I am trying to close a window from its ViewModel. I am using the MVVM pattern. I have tired to get the window using;
Window parentWindow = Window.GetWindow(this);
But I cannot do this, how do I get the window of the ViewModel so I am able to close the window. I want to be able to do this in code.
Can you find the parent window in code?
ViewModels should not be referencing the View in any way, including closing windows, in MVVM.
Instead, communication between the View and ViewModel is typically done through some kind of Event or Messaging System, such as Microsoft Prism's EventAggregator, or MVVM Light's Messenger
For example, the View should subscribe to listen for event messages of type CloseWindow, and when it receives one of those message it should close itself. Then the ViewModel simply has to broadcast a CloseWindow message anytime it wants to tell the View to close.
There's a brief overview of event systems in MVVM, and some examples, on my blog post about Communication between ViewModels if you're interested
yes referencing view in viewmodel isn't best practice. WHY? because when you unit test your viewmodel it is require you to instantiate view, for small view will not difficult to do that, but for a complex view with complex tree of dependency? that wont be good.
for me, the easiest way to do communication with view is by passing IInputElement on viewmodel constructor. the bennefit of IInputElement is Routed Event backbone, it has RaiseEvent and AddHandler method required for routed event. thus you can bubble/tunnel/direct event to any view or viewmodel on your application freely without any additional library.
here is my the simplified code on viewmodel but remember this technique only work for view first approach
public class MyViewModel : INotifyPropertyChanged
{
public static readonly RoutedEvent RequestCloseEvent = EventManager.RegisterRoutedEvent("RequestClose",
RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyViewModel));
private IInputElement dispatcher;
public MyViewModel(IInputElement dispatcher)
{
this.dispatcher = dispatcher;
}
public void CloseApplication()
{
dispatcher.RaiseEvent(new RoutedEventArgs(RequestCloseEvent));
}
}
on your View simply
DataContext = new MyViewModel(this)
//notice "this" on the constructor
and the root view (Window) of your application simply
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
AddHandler(MyViewModel.RequestCloseEvent, new RoutedEventHandler(onRequestClose));
}
private void onRequestClose(object sender, RoutedEventArgs e)
{
if (MessageBox.Show("Are you sure you want to quit?", "Confirmation", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
Close();
}
}
}
and because IInputElement is interface rather than class, you easily create a mock class for your unit test
var target = new MyViewModel(new DispatcherMock)
or you can use mock library like RhinoMocks
for further reading, you can learn more about how to use Routed Event
Let the ViewModel do this, if really in need.
The Models says for example, that there are no longer valid data
pass that information to the ViewModel
the ViewModel recognizes, that it can no longer display anything
and then closes the window.
An empty view is the normal way of expressing that there are no more data
You can define an action in your ViewModel
public Action CloseAction { get; set; }
then, in your window (for example in the DataContextChanged) you can set this action :
((IClosable)viewModel.Content).CloseAction = () => System.Windows.Application.Current.Dispatcher.Invoke(Close());
Well, all this is part of a bigger dependency injection pattern, but basic principle is here...
Next, you juste need to call the action from the VM.
There is a useful behavior for this task which doesn't break MVVM, a Behavior, introduced with Expression Blend 3, to allow the View to hook into commands defined completely within the ViewModel.
This behavior demonstrates a simple technique for allowing the
ViewModel to manage the closing events of the View in a
Model-View-ViewModel application.
This allows you to hook up a behavior in your View (UserControl) which
will provide control over the control's Window, allowing the ViewModel
to control whether the window can be closed via standard ICommands.
Using Behaviors to Allow the ViewModel to Manage View Lifetime in M-V-VM
http://gallery.expression.microsoft.com/WindowCloseBehavior/

MVP: 3rd party controls, How much logic can be put in View layer

I'm learning MVP pattern, but still have some doubts.
Martin Hunter in his MVC/MVP overview wrote:
In MVP, the view becomes an ultra-thin component whose purpose is purely to provide a presentation to the user. The view catches and handles events raised by the user, but forwards these directly to the presenter who knows how to deal with them.
(...)
However, with MVP the view catches events raised and forwards them to the controller (presenter)
This is fine with buttons and text boxes, but what in case there are some more complex controls? Lets say I'm using 3rd party components, like Devexpress's TreeList control. Assume I want to dinamically build sub-nodes when user clicks expand button "+". Not using any pattern I could code this like that:
private void BeforeExpand_EventHandler(object sender, BeforeExpandEventArgs e)
{
TreeList treeList = sender as TreeList;
MyModelObject nodeObj = e.Node.Tag as MyModelObject;
treeList.BeginUnboundLoad();
//Create sub-nodes depending on nodeObj
treeList.EndUnboundLoad();
}
As you can see there are some View-objects, like BeforeExpandEventArgs, TreeListNode, some specific actions like BeginUnboundLoad(), and so on. In that case my View layer cannot be "ultra thin". I cannot pass directly to Presenter objects like BeforeExpandEventArgs because it would affect the Presenter with some View stuff.
My question is then: How much logic I can put into View layer? For example, is code presented below ok?
private void BeforeExpand_EventHandler(object sender, BeforeExpandEventArgs e)
{
TreeList treeList = sender as TreeList;
MyModelObject nodeObj = e.Node.Tag as MyModelObject;
treeList.BeginUnboundLoad();
e.Node.Nodes = this.presenter.GetNodes(nodeObj);
treeList.EndUnboundLoad();
}
I think the View is responsible for handling this issue.The idea of MVP(MVC) is that you can switch to other View without changing Model & Presenter at least theoretically ;). So that the View logic may stay at view layer as you did.
One thing I don't agree in your sample is a reference to the Presenter.You should do the opposite. The presenter has to have reference to View as well as Model objects. In this case the View invokes its event which Presenter has already listen and Presenter returns array of nodes to View.

Categories