簡體   English   中英

MVVM UI控件與WPF相關的用戶可見性

[英]MVVM UI Control user dependent Visibility with WPF

這更多是MVVM應用程序設計問題。 我正在嘗試實現一個非常基本的基於用戶的權限管理,其中,我的應用程序中某些控件的可見性是從“當前用戶角色”派生的。 這是我的簡化模型:

public class User
{
 public string UserName {get;set;}
 public Role UserRole {get;set;}
}

public enum Role
{
  Developer,
  BusinessAnalyst
}

public class MenuItemModel
{
   public ICommand Command {get;set;}
   public string Header {get;set;}
   public bool Visible {get;set;}
   private List<MenuItemModel> _Items;
   public List<MenuItemModel> Items
   {
        get { return _Items ?? (_Items = new List<MenuItemModel>()); }
        set
        {
            _Items = value;
        }
    }
}

我的MainViewModel包含以下屬性:

public class MainViewModel : ViewModelBase<MainViewModel>
{
    private ObservableCollection<MenuItemModel> _MainMenu;
    public ObservableCollection<MenuItemModel> MainMenu
    {
        get { return _MainMenu; }
        set
        {
            _MainMenu = value;
            NotifyPropertyChanged(x=>x.MainMenu);
        }
    }
    private User _CurrentUser;
    public User CurrentUser
    {
        get { return _CurrentUser; }
        set { 
            _CurrentUser = value;
            NotifyPropertyChanged(x=>x.CurrentUser);
        }
    }
}

這是我聲明和綁定菜單的XAML:

<Menu DockPanel.Dock="Top" ItemsSource="{Binding Path=MainMenu}">
            <Menu.ItemContainerStyle>
                <Style>
                    <Setter Property="MenuItem.Header" Value="{Binding Path=Header}"/>
                    <Setter Property="MenuItem.ItemsSource" Value="{Binding Path=Items}"/>
                    <!-- How to bind Visibility????-->
                    <!--Setter Property="MenuItem.Visibility" /-->
                </Style>
             </Menu.ItemContainerStyle>
         </Menu>

現在在這里我的要求:

  1. 某些UI控件(例如MenuItems)的可見性取決於User.Role。 例如:MenuItemA對Role.Developer應該可見,但對Role.BusinessAnalyst不可見
  2. 對於多個角色,某些控件可能可見(例如,開發人員和業務分析師)

到目前為止我的兩個選擇

  1. 創建一個自定義轉換器,該轉換器具有根據允許的角色派生可見性並將其綁定到MenuItem.Visibility Value屬性的邏輯。 問題在於:a)此控件允許的角色必須在運行時傳遞,因為它們來自數據庫,並且您無法將CommandParameters綁定到角色集合。 b)轉換器將如何訪問User.Role以獲取可見性?
  2. 在我的UI模型(例如MenuItemModel)的屬性內創建可見性邏輯。 但是在這里,我不想在User和MenuItemModel類之間創建依賴關系。

什么是最干凈的方法基於User.Role動態派生UI控件可見性,而不會遇到緊密耦合的場景(依賴項)?

謝謝!

解決方案:這就是我最終根據@fmunkert建議解決它的方式。 注意,我必須將MenuItemModel.Items屬性更改為List才能訪問“ RemoveAll”方法:

    public MainViewModel()
    {
        //Create a new User with a Role
        InitializeUser();
        //Get all the Menus in the application
        List<MenuItemModel> allItems = GetAllMenus();
        //Remove recursively all Items that should not be visible for this user
        allItems.RemoveAll(x=>!IsVisibleToUser(x));
        //Set my MainMenu based on the filtered Menu list
        _MainMenu = new ObservableCollection<MenuItemModel>(allItems);
    }

    private void InitializeUser()
    {
        CurrentUser = new User {UserName = "apsolis", UserRole = Role.Developer};
    }

這是我的MainViewModel中遞歸地刪除禁用項目的方法:

    /// <summary>
    /// Method to check if current MenuItem is visible to user
    /// and remove items that are forbidden to this user
    /// </summary>
    /// <param name="m"></param>
    /// <returns></returns>
    public bool IsVisibleToUser(MenuItemModel m)
    {
        if (m.Items != null && m.Items.Count > 0)
        {
            m.Items.RemoveAll(y=>!IsVisibleToUser(y));
        }
        return m.Roles == null || m.Roles.Contains(CurrentUser.UserRole);
    }

這似乎工作正常

由於您是在ViewModel中生成菜單項,因此建議不要使用MenuItem.Visibility 而是讓ViewModel確定允許用戶查看哪些菜單項,並僅用該菜單項的子集填充MainMenu集合。 即您的MainViewModel必須知道允許用戶查看哪些菜單項。

即,您可以在MainViewModel的構造函數中使用如下代碼:

_MainMenu = new ObservableCollection<MenuItemModel>(_allMenuItems.Select(m => IsVisibleToUser(m)));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM