Я думаю, что «наследование» не подходит вам в этом контексте, хотя я не знаю, что это такое.
«Наследование» подразумевает определенный тип отношений между классами и подклассами. Вы можете создавать базовые классы модели представления и наследовать от них, но вы не можете реально сделать это с помощью представлений, потому что представления строятся с помощью композиции, а не с помощью реализации свойств и методов.
Конечно, имеет смысл создать базовый класс модели представления, который будет выполнять то, что вы описываете. Я делаю это прямо сейчас в проекте, над которым я работаю. У меня есть класс модели представления, который поддерживает ссылки в меню, предоставляя коллекцию CommandLinks
. Каждый объект CommandLink
в коллекции предоставляет текст ссылки, более подробное описание и Command
. В представлении у меня есть DataTemplate
, который размещает Hyperlink
и TextBlock
внутри DockPanel
, а DataTemplate
для модели представления содержит ItemsControl
, привязанный к коллекции CommandLinks
на мой взгляд модель. Подклассы модели представления заполняют их коллекцию CommandLinks
, и Боб - ваш дядя. Моему приложению не нужно заполнять коллекцию CommandLinks
в базовом классе, потому что команды различны для каждого класса модели представления, но нет никаких причин, по которым я не смог.
Я бы не назвал это "визуальным наследованием". Потому что, если я решу, что хочу по-другому разложить класс модели представления, я не смогу просто переопределить DataTemplate
в своей реализации. Я должен построить новый DataTemplate
специально для этого класса. Это где концепция наследования начинает разрушаться.
Если я установлю DataContext
из ContentPresenter
(скажем) для экземпляра моей модели представления, WPF просмотрит словари ресурсов, чтобы найти DataTemplate
с ключом типа объекта. Он будет использовать шаблон базового типа, если производный тип не имеет определенного. Но если производный тип имеет определенный, WPF будет использовать его вместо этого. И у вас нет способа унаследовать один шаблон от другого, поэтому шаблон подкласса не может просто волшебно выглядеть как шаблон базового класса.
В итоге вы реализуете это так:
<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>
Это не действительно наследование. Для кого-то нет способа реализовать собственный производный класс без изменения шаблона данных для базового класса.
Вы можете обойти это, дав ключ шаблона контейнера. Но тогда человек, реализующий представление, должен знать об этом. Он не может просто сделать это, например:
<ItemsControl ItemsSource="{Binding MyObjectList}"/>
но вместо этого должен сделать что-то вроде:
<ItemsControl ItemsSource="{Binding MyObjectList}" ItemTemplate="{StaticResource MyBaseClassTemplate}"/>
Мне это не кажется огромной ценой. Но тогда я обычно являюсь единственным разработчиком своих проектов.