View image differently depending on the WPF user ' s role



  • Hello, everyone. Problem. There are users with different roles, such as: AdminMotorlaser.

    I want to be able to limit what users can see on the basis of their role. The same. View may be hidden, blocked or new controls will be available, depending on the role of the current user.

    How can such a task be accomplished as flexibly and correctly in the context of the MVM pathter?



  • In my view, it makes sense to create a hierarchy of presentation models:

    abstract class BaseRoleVm { ... }
    class UserRoleVm : BaseRoleVm { ... }
    class ModeratorRoleVm : BaseRoleVm { ... }
    class AdminRoleVm : BaseRoleVm { ... }
    

    Then, for each non-exhaustive ViewModel to be presented (to reuse the code in the submission, styles, contrasts, resource dictionaries can be used).

    Most of the windows will have to start a type of thing. BaseRoleVmto be given the right heir:

    class MainVm
    {
        public BaseRoleVm Role { get; set; }
    
    void UseAdminRole()
    {
        Role = new AdminRoleVm();
    }
    ...
    

    }

    Such an approach would make it easy to change roles, ensure their independence from allow each other, allow for the addition/play of roles without interference with the logic of the main window.

    UPD

    This is a small example based on resource dictionaries:

    Presentation models (to be found in 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();
    }
    

    }

    Submissions

    // содержимое файла "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 chabloon sector:

    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&lt;DataTemplate&gt;()
            .SingleOrDefault(_ =&gt; ReferenceEquals(_.DataType, itemType));
    }
    

    }

    At the level of perception, there is no connection. ContentControl Uses written ViewModelTemplateSelector To find the right templates. There is some:

    1. Ooh. ContentControl Change. Content (Incorporated PropertyChanged)
    2. ContentControl Calling. ViewModelTemplateSelector Method SelectTemplate and transfer there Content as item
    3. ViewModelTemplateSelector Finds a file with a type-based presentation and gets out of there. DataTemplate
    4. ContentControl It's a picture. Content using the DataTemplate




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2