1

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?

2
  • Please explain why you want to use Properties and Events of the View in the ViewModel so we can help you to get it right. This is not the way to do MVVM. In MVVM the ViewModel does not know anything about the View except for it having a DataContext. Commented Jan 12, 2012 at 18:27
  • Erno: I've changed the Question a bit. " In this example I wanna Bind(TwoWay Bind) IsLast Property with a visibility of a button." Commented Jan 12, 2012 at 18:39

4 Answers 4

4

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

Sign up to request clarification or add additional context in comments.

Comments

2

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).

Comments

2

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.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.