In my opinion, it makes sense to create a hierarchy of view models:
abstract class BaseRoleVm { ... } class UserRoleVm : BaseRoleVm { ... } class ModeratorRoleVm : BaseRoleVm { ... } class AdminRoleVm : BaseRoleVm { ... }
Then for each non-abstract ViewModel, create a view (you can use styles, controls, resource dictionaries to reuse the code in the view).
In the main window, you will need to create a property of type BaseRoleVm , which will be assigned the desired successor:
class MainVm { public BaseRoleVm Role { get; set; } void UseAdminRole() { Role = new AdminRoleVm(); } ... }
Such an approach will make it easy to make changes to the views / role view models, ensure their independence from each other, provide the ability to add / remove roles without interfering with the logic of the main window.
UPD
Here is a small example based on resource dictionaries:
View models (located in the ViewModels folder):
public abstract class BaseRoleVm : BaseVm { public abstract string Name { get; } } public class AdminRoleVm : BaseRoleVm { public override string Name { get { return "Админ"; } } } public class UserRoleVm : BaseRoleVm { public override string Name { get { return "Юзер"; } } } public class MainVm : BaseVm { public BaseRoleVm SelectedRole { get { return _selectedRole; } set { SetField(ref _selectedRole, value); } } private BaseRoleVm _selectedRole; public BaseRoleVm[] Roles { get; } public MainVm() { // формировать список или создавать нужную модель представления можно через MEF или Reflection. // тогда вы не будете зависеть от перечня ролей Roles = new BaseRoleVm[] { new AdminRoleVm(), new UserRoleVm(), }; SelectedRole = Roles.FirstOrDefault(); } }
Views (lie in the Views folder)
// содержимое файла "AdminRole.xaml" (тип Resource Dictionary) <ResourceDictionary ...> <DataTemplate DataType="{x:Type vm:AdminRoleVm}"> <TextBlock Text="Админское представление"/> </DataTemplate> </ResourceDictionary> // содержимое файла "UserRole.xaml" (тип Resource Dictionary) <ResourceDictionary ...> <DataTemplate DataType="{x:Type vm:UserRoleVm}"> <TextBlock Text="Представление юзера"/> </DataTemplate> </ResourceDictionary> // главное окно // содержимое файла "Main.xaml" (тип Window) <Window ...> <Window.DataContext> <vm:MainVm/> </Window.DataContext> <Window.Resources> <helpers:ViewModelTemplateSelector x:Key="ViewModelTemplateSelector"/> </Window.Resources> <StackPanel> <ComboBox ItemsSource="{Binding Roles}" SelectedItem="{Binding SelectedRole}" DisplayMemberPath="Name"/> <ContentControl Content="{Binding SelectedRole, UpdateSourceTrigger=PropertyChanged}" ContentTemplateSelector="{StaticResource ViewModelTemplateSelector}"/> </StackPanel> </Window>
And the simplest template selector:
public class ViewModelTemplateSelector : DataTemplateSelector { public override DataTemplate SelectTemplate(object item, DependencyObject container) { if (item == null) { return null; } var itemType = item.GetType(); var resourceDictonary = new ResourceDictionary { Source = new Uri(string.Format( "pack://application:,,,/{0};component/Views/{1}.xaml", itemType.Assembly.FullName, itemType.Name.Replace("Vm", string.Empty))) }; return resourceDictonary .Values .OfType<DataTemplate>() .SingleOrDefault(_ => ReferenceEquals(_.DataType, itemType)); } }
At the level of representation, roles are unrelated. ContentControl uses the written ViewModelTemplateSelector to search for the right templates. Something like this happens:
ContentControl changes Content (PropertyChanged worked)ContentControl calls the SelectTemplate method on the ViewModelTemplateSelector and passes the Content there as an itemViewModelTemplateSelector finds a file with a view based on the type name and pulls out a DataTemplate .ContentControl displays Content using the found DataTemplate