how to relate View and Viewmodel when multiple views implements same interface

Topics: Prism v4 - WPF 4
Nov 23, 2012 at 7:10 AM

1) [Export("UnifiedSearchResultsViewModel", typeof(ISearchResultsViewModel))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class UnifiedSearchResultsViewModel : ViewModel<ISearchResultsView>, ISearchResultsViewModel
    {
     }

This is my viewmodel class

2) [Export("UnifiedSearchResultsView", typeof(ISearchResultsView))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public partial class UnifiedSearchResultsView: UserControl, ISearchResultsView
    {

}

This is my view class

How can I make sure that when I resolve my viewmodel class "UnifiedSearchResultsViewModel", it should load the "UnifiedSearchResultsView" only.. I have so many other views/viewmodels which inherits from ISearchresultsView/ISearchResultsViewModel. Should I create a seperate interface for each view?Any idea?

Developer
Nov 23, 2012 at 2:15 PM

Hi,

Based on my understanding if you are exporting different classes implementing the same interface and you are also defining a contract came while doing so, like in the code snippets above, you should be able to distinguish from the different exported implementations by defining different contract names in each Export attribute, this way this contract name could be used to specify which implementation you will use when defining your Import attributes. For example by defining your attribute like this:

[Import("customSearchResultsViewModel",typeof(ISearchResultsViewModel))]
For more information on the different approaches you could use when importing and exporting using the MEF container you could check the MEF Programming Guide.

On the other hand, take into account that when applying the MVVM pattern  your view models should ideally not depend on any specific implementation of the view, as they should have no explicit knowledge of the specific visual elements in the view, in order to provide a clean separation between application logic and the UI makes your application.

You could find more information about this in the following chapter of the Prism documentation:

I hope you find this handy,

Agustin Adami
http://blogs.southworks.net/aadami

Nov 24, 2012 at 6:30 PM

Thank you Adami for the comment. but I think I didn't explain my issue.Please see below explanation again.

here are my classes.

1) [Export("UnifiedSearchResultsViewModel", typeof(ISearchResultsViewModel))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class UnifiedSearchResultsViewModel : ViewModel<ISearchResultsView>, ISearchResultsViewModel
    {
          // Here the parameter is ISearchResultsView, and my two views implements same interface
          public UnifiedSearchResultsViewModel(ISearchResultsView view
          {
          }
     }

This is first viewmodel class

2) [Export("UnifiedSearchResultsView", typeof(ISearchResultsView))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public partial class UnifiedSearchResultsView: UserControl, ISearchResultsView
    {
   
}

This is my first view class

3) [Export("CustomerSearchResultsViewModel", typeof(ISearchResultsViewModel))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class CustomerSearchResultsViewModel : ViewModel<ISearchResultsView>, ISearchResultsViewModel
    {
          // Here the parameter is ISearchResultsView, and my two views implements same interface
          public CustomerSearchResultsViewModel(ISearchResultsView view
          {
          }
     }

This is second viewmodel class

4) [Export("CustomerSearchResultsView", typeof(ISearchResultsView))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public partial class CustomerSearchResultsView: UserControl, ISearchResultsView
    {
   
}

This is my second view class

Now While resolving viewmodel class, I am using following code:

ISearchResultsViewModel searchResultsViewModel = _container.Resolve<ISearchResultsViewModel>("UnifiedSearchResultsViewModel");

ISearchResultsViewModel searchResultsViewModel = _container.Resolve<ISearchResultsViewModel>("CustomerSearchResultsViewModel");

Now the issue is how viewmodel knows that which ISearchResultsView needs to be loaded?? Please suggest

 

 

 

Developer
Nov 27, 2012 at 2:32 PM
Edited Nov 27, 2012 at 2:32 PM

Hi,

Based on my understanding you could try defining an Import attribute with a contract name in the constructor of your view model to specify which implementation will be used for each case, for example your CustomerSearchResultsViewModel could look like this

[Export("CustomerSearchResultsViewModel", typeof(ISearchResultsViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
    public class CustomerSearchResultsViewModel : ViewModel<ISearchResultsView>, ISearchResultsViewModel
    {
       
          public CustomerSearchResultsViewModel([Import("CustomerSearchResultsView",typeof(ISearchResultsView ))] ISearchResultsView view) 
          {
          }
     }

 

Also, a similar approach could be implemented by using Property Injection, or as an alternative approach you could as mentioned above define different interfaces for each kind of your views. Which approach you take will depend on your personal preferences.

On the other hand, take into account that in order to resolve instances when using MEF, this could be achieve through the CompositionContainer class in which case the call to resolve an instance could be like this (this will differ when using Unity as your container, in which case the method called will be similar like the one you posted above to resolve the view models classes):

ISearchResultsViewModel searchResultsViewModel = this.Container.GetExportedValue<ISearchResultsViewModel>("CustomerSearchResultsViewModel");

Note that, resolving instances in MEF could also be achieved by using Import attribute in your classes or the Service Locator.

For more information about this you could also check the following chapter of the Prism documentation:

I hope you find this helpful,

Agustin Adami
http://blogs.southworks.net/aadami

Nov 27, 2012 at 5:29 PM

Thank you very much Adami, it worked... thanks a ton...