C# – WPF MVVM and View inheritance

cmvvmwpf

I have about a dozen different views, which are pretty much identical except for the names of the properties they bind to. For example, the below sections are form two different views:

<TextBlock Text="{Binding PersonName}">       
<GroupBox Header="{Binding PersonName}">
  <ComboBox Text="{Binding SelectedPersonName}" SelectedItem="{Binding SelectedPerson}" ItemsSource="{Binding People}" DisplayMemberPath="PersonName"/>
</GroupBox>
<igDP:XamDataGrid DataSource="{Binding PersonEntries}"


<TextBlock Text="{Binding CarName}">       
<GroupBox Header="{Binding CarName}">
  <ComboBox Text="{Binding SelectedCarName}" SelectedItem="{Binding SelectedCar}" ItemsSource="{Binding Cars}" DisplayMemberPath="CarName"/>
</GroupBox>
<igDP:XamDataGrid DataSource="{Binding CarEntries}"

Note that the only real differences between these to blocks are the names of the bindings used (Person vs Car).

I was thinking of maybe creating one BaseView class that the other views inherit from. This base class would use generic enough binding names so that it can be reused, such as:

<TextBlock Text="{Binding DataItemName}">       
<GroupBox Header="{Binding DataItemName}">
  <ComboBox Text="{Binding SelectedDataItemName}" SelectedItem="{Binding SelectedDataItem}" ItemsSource="{Binding DataItems}" DisplayMemberPath="DataItemName"/>
</GroupBox>
<igDP:XamDataGrid DataSource="{Binding DataItemEntries}"

This way, my PersonsView and CarsView can inherit from BaseView and that's it. I would also have to make changes to the ViewModels though, so that they expose the correctly named properties, such as DataItem. I guess I could create a base ViewModel interface that exposes the desired properties and have the other ViewModels implement that.

Any thoughts on the above? Would it be a bad idea to try to create a base view or base view model as I described?

Thanks.

Best Answer

You're really going to create the inheritance in your view models, not your views. I'd define an ItemViewModelBase class that exposes ItemName, Items, and SelectedItemName properties and derive my view models from it.

The views themselves don't really "inherit" per se. In fact, unless you need customization in the view, you don't need multiple views: you only need one view that presents ItemViewModelBase objects.

Of course, if you do need the views to be different, you can do a certain amount of customization, e.g.:

<DataTemplate DataType="{x:Type CarsViewModel}">
   <DockPanel>
      <Label DockPanel.Dock="Top">Cars</Label>
      <local:ItemView/>
   </DockPanel>
</DataTemplate>

This is a cool idea for another reason. Right now, if you don't provide a data template, whenever WPF presents an object it creates a TextBlock containing object.ToString(). Implementing a generic base class gives you a way to globally override this behavior just by creating one data template, e.g.:

<DataTemplate DataType="{x:Type ItemViewModelBase}">
   <TextBlock Text="{Binding ItemName}"/>
</DataTemplate>

That's not easier than just overriding ToString() to return ItemName (which is where I'd start), but if (for instance) you want a ToolTip that displays detailed information when the user mouses over it, you just add it to this one template and it works everywhere in your UI.