0

I want to build a view, which will contain an injected view into a region (both will have their own ViewModels).

The first view will contain some action controls (new, save, delete, load buttons) that will "execute" over the second view, which will contain some field controls (TextBoxes for user input).

The first view (and its viewmodel) cannot the real (final) type of the view that is into it, because this type can vary (e.g.: customer fields, products fields, user fields).

The question is: How can I reach this by using MVVM in a right way?

H.B.
  • 166,899
  • 29
  • 327
  • 400
Diego Stiehl
  • 403
  • 8
  • 25

1 Answers1

2

If I understand your question right, you have a View containing a generic object, and you want a different template based on what the generic object is.

If that's the case, use a ContentControl and DataTemplates

<ContentControl Content="{Binding SomeGenericObject}">
    <ContentControl.Resources>
        <DataTemplate DataType="{x:Type local:CustomerViewModel}">
            <local:CustomerView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:ProductViewModel}">
            <local:ProductView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:OrderViewModel}">
            <local:OrderView />
        </DataTemplate>
    </ContentControl.Resources>
</ContentControl>

As for handling the generic CRUD operations in your ViewModel, see my answer to your other question about using a generic interface.

Community
  • 1
  • 1
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • Hi omnipresent Rachel. I think (again) you gave me perfect answer. Now I have to take some "shots" about this feature. I'll get back soon. – Diego Stiehl Jan 20 '12 at 23:59
  • OK... There is a problem. I'm using Prism, and the "master page" view must be defined by the shell project (or a common or default module), and all the internal views will be created into their respective modules. So the "master page" view cannot know a thing about the internal views. Can you understand? What could I do? Thanks. – Diego Stiehl Jan 21 '12 at 00:53
  • 1
    @DiegoStiehl I tend to use `ConentControls` and just bind the `Content` to whatever ViewModel is needed. Then use `DataTemplates` to tell WPF how to draw each ViewModel. If you're interested, I wrote something about navigation with MVVM [here](http://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/), which has an example of changing the current content using `ContentControls` and `DataTemplates` – Rachel Jan 21 '12 at 21:13
  • Hi Rachel... Your example does not fit to my problem. Remember that I'm using prism and the views and viewmodels are created by each module and the shell project is the shell and it can't know a thing about the modules. This situation makes impossible both your `ContentControl` and navigation examples. Thanks. – Diego Stiehl Jan 23 '12 at 15:26
  • 1
    @DiegoStiehl It works fine in Prism - I've done it before. Make each Module store its DataTemplates in a ResourceDictionary, and load all the resource dictionaries into the application's Merged Dictionaries at Runtime. As for your other question, put all your generic classes and interfaces in a common library that is accessible by all other modules. Your main ViewModel doesn't need to know the exact type of an object to work with it - only that it inherits from a specific interface. – Rachel Jan 23 '12 at 15:30
  • Well. The use of ResourceDictionary sounds good to me, but I'm fairly new in the world of WPF/MVVM/Prism (and other things hehe) and I have to learn how to work with it. Do you have any good example? Thanks – Diego Stiehl Jan 23 '12 at 15:35
  • 1
    @DiegoStiehl Usually I create an interface in my common project, and implement it in my main project. The modules use this common interface to add their resources to the application when the module gets loaded. There's a similar example in [this SO answer](http://stackoverflow.com/a/1172794/302677) – Rachel Jan 23 '12 at 15:43
  • I liked and used the example code. Now, how can I tell my `ContentControl` the source of the `DataTemplate`? – Diego Stiehl Jan 23 '12 at 17:20
  • @DiegoStiehl Just bind the `Content` property to your `ViewModel` object. `` Providing you have a `DataTemplate` specified for that ViewModel's type somewhere in your application's resources, it will automatically draw the ViewModel using the correct `DataTemplate`. – Rachel Jan 23 '12 at 17:47
  • But when I do not want to use these `DataTemplates`, what would happen? – Diego Stiehl Jan 23 '12 at 18:05
  • @DiegoStiehl Then the View needs to specify what `DataTemplate` to use for each ViewModel type, so it needs to contain a reference to every single ViewModel type to do that. It completely breaks your separation of UI and application logic – Rachel Jan 23 '12 at 18:09
  • Hi... I'm trying to use this approach to provide access to an entity called `Operation` -> ``. How can I bind the `Operation` properties in the "injected" view `CadastroOperacaoView` which had the `Content` set in the "master page" view using ``? – Diego Stiehl Jan 24 '12 at 11:49
  • @DiegoStiehl I'm afraid I don't understand what you're trying to do. Your `GenericView` should bind to your `IGenericInterface`, and it should contain the generic buttons like Save, Cancel, etc. Inside the `GenericView` there should be a `ContentControl` bound to the ViewModel that inherits `IGenericInterface`, and it should be drawn using your `SpecificView` with a `DataTemplate`. Your `SpecificView` should never have to access the Generic one, and vise versa. Anything the `GenericView` needs should be in `IGenericInterface`, although it's implementation might be in your `SpecificViewModel` – Rachel Jan 24 '12 at 13:08
  • I'm sorry that you're afraid you don't understand what I'm trying to do. I'm trying to to learn WPF and also create "my practices" to be adopted throughout my team's project. I tried to explain my problem [in this new question](http://stackoverflow.com/q/8987709/1148768). Thanks. – Diego Stiehl Jan 24 '12 at 13:44