tags:

views:

231

answers:

2

I've been looking through the PRISM 2 samples for ideas about how to best approach a new application I'm working on, which will be a PRISM 2/WPF app. Looking in particular at the View Injection sample application that ships with PRISM I've noticed that all of the views implement an interface which allows the presenter (or ViewModel) to interact with the View.

In the past I've done this the opposite way round, I inject the presenter into the view so that the view can directly call to methods on the presenter a bit like this:

    public partial class SomeView : ModuleBase
    {

        private ISomePresenter _somePresenter;

        public SomeView (ISomePresenter somePresenter):this()
        {
            // Give the view a reference to the presenter
            _somePresenter = somePresenter;
            // Bind the View to the presenter
            DataContext = _somePresenter;
        }

    private void btnSubmit_Click(object sender, RoutedEventArgs e)
    {
        // The view can call actions directly on the presenter (OK I should probably use a command for this)
        _somePresenter.SomeAction();
    }
}

The technique above seemed reasonable enough to me, but looking at the samples I'm starting to question the approach. Does anyone have views (no pun intended) on the best way to go about this?

  • Add the presenter to the view and get the view to interact with the presenter
  • Add the view to the presenter and get the presenter to interact with the view
  • Something totally different that I haven't thought of yet?
+2  A: 

I think it's all a matter of taste. Personally, I enjoy the way you see it in samples you are looking at. IView has one method, thats SetViewModel(...). IViewModel has a property called View of type Object, that essentially returns the DI instantiated IView.

The reason I like this way is I almost always want to create a ViewModel first and I want nobody in the code to be able to do anything with my IView, except get reference to the instance (for view injection or binding the view to say a ContentControl), which is why its of type object. If any code needs to talk to the View, for me, it's always via the VM...and even then the view gets updated usually via binding. It would feel odd to go from the View->ViewModel->UpdateBinding->View, than it is, VM->UpdateBinding->View

To answer the question, I generally don't need a reference to the presenter in the codebehind. Usually I can handle that with commands from the view being bound to the VM. In some cases, you might want to keep reference to the presenter to do what you have in your example, but it is avoidable given the correct toolset (makes SL harder that it doesn't have built in commands).

Like I said, it's all a matter of taste...

-Jer

Jeremiah Morrill
+3  A: 

The most common approach to map a ViewModel to a View in MVVM is to use a DataTemplate :

<DataTemplate DataType="{x:Type vm:SomeViewModel}">
    <v:SomeView />
</DataTemplate>

When you display a ViewModel instance in a ContentControl or ItemsControl, WPF will automatically instantiate the appropriate View for the ViewModel, and set the View's DataContext to the ViewModel instance.

That way, you don't have any reference to the View in the ViewModel, and the View only references the ViewModel through the DataContext property. In case you really need to access the ViewModel in the View's code-behind, you can always cast the DataContext (but this implies that the View knows about the ViewModel's actual type, which induces coupling)

Thomas Levesque