tags:

views:

39

answers:

3

Hi,

I want to write a Detail(Info) screen with MVVM pattern on my framework. There will be a base detail view model and view which has a toolbar and buttons on this toolbar(save, delete, new buttons, etc.). And users of this framework are going tor write his/her detail(info) screens without using manually added toolbar. Their detail(info) screen's view model will be inherited from framework's detail(info) view model. So the toolbar is automatically added to his/her detail(info) screens.

Has anybody implemented a situation like this before or can you give me a pattern or strategy on this issue? Thanks all.

+1  A: 

I don't have visual inheritance in my MVVM - I design my program to fit into the platform not to explicitly use unsupported techniques.

I build common elements either as a control that the view uses or as a class derived from Decorator or ContentControl that the framework inserts automatically (in that case the view becomes a child of that control).

Even if you find some workaround that will let you use visual inheritance it's not supported and a sure way to get into trouble later when you hit the limitations of your workaround

Nir
+2  A: 

I don't use visual inheritance. Instead I have main window with buttons toolbar and area where I plug user controls.

ViewModels for each user control implement interface that have commands for buttons on toolbar, so I can bind buttons to command implementation in each user control.

See example in this MSDN article: WPF Apps With The Model-View-ViewModel Design Pattern

zendar
+1  A: 

I think "inheritance" is not the right term for you to be using in this context, though I don't know what is.

"Inheritance" implies a specific kind of relationship between classes and subclasses. You can build view model base classes and inherit from them, but you can't really meaningfully do that with views, because views are built through composition and not by implementing properties and methods.

It certainly can make sense to build a view model base class that does what you describe, though. I'm doing that right now in a project I'm working on. I have a view model class that supports links in a menu by exposing a CommandLinks collection. Each CommandLink object in the collection exposes link text, a more verbose description, and a Command. In the view, I have have a DataTemplate that lays out the Hyperlink and TextBlock inside a DockPanel, and the DataTemplate for the view model contains an ItemsControl that's bound to the CommandLinks collection in my view model. The view model subclasses populate their CommandLinks collection, and Bob's your uncle. My application doesn't need to populate the CommandLinks collection in the base class, because the commands are different for every view model class, but there's no reason that I couldn't.

I wouldn't call this "visual inheritance," though. Because if I decide that I want to lay out a specific view model class differently, I can't just override the DataTemplate in my implementation of it. I have to build a new DataTemplate specifically for that class. This is where the inheritance concept starts to break down.

If I set the DataContext of a ContentPresenter (say) to an instance of my view model, WPF will look through the resource dictionaries to find a DataTemplate keyed by the object's type. It'll use the base type's template if the derived type doesn't have one defined. But if the derived type does have one defined, WPF will use that one instead. And you don't really have a way of inheriting one template from another, so the subclass's template can't just magically look like the base class's template.

You end up implementing it like this instead:

<DataTemplate DataType="{x:Type MyBaseClass}">

   <DataTemplate.Resources>
       <DataTemplate DataType="{x:Type MyBaseClass}"> ...
       <DataTemplate DataType="{x:Type MyDerivedClass1}"> ...
       <DataTemplate DataType="{x:Type MyDerivedClass2}"> ...
   </DataTemplate.Resources>

   <DockPanel>
      <ItemsControl DockPanel.Dock="Left" ItemsSource="{Binding CommandLinks}"/>
      <ContentPresenter DataContext="{Binding}"/>
   </DockPanel>

</DataTemplate>

This isn't truly inheritance. There's no way for someone to implement their own derived class without modifying the data template for the base class.

You can get around this, sort of, by giving the container template a key. But then the person implementing the view needs to know about this. He can't just do this, for instance:

<ItemsControl ItemsSource="{Binding MyObjectList}"/>

but instead has to do something like:

<ItemsControl ItemsSource="{Binding MyObjectList}" ItemTemplate="{StaticResource MyBaseClassTemplate}"/>

That doesn't seem like an enormous price to pay, to me. But then I'm usually the only developer on my projects.

Robert Rossney