这更像是一个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>
现在我的要求:
到目前为止我的两个选择
根据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);
}
这似乎工作正常
答案 0 :(得分:4)
由于您在ViewModel中生成菜单项,我建议您根本不使用MenuItem.Visibility
。相反,让ViewModel确定允许用户查看哪些菜单项,并仅使用该子菜单项填充MainMenu集合。即您的MainViewModel必须知道允许用户查看哪些菜单项。
即,你可以在MainViewModel的构造函数中使用类似的东西:
_MainMenu = new ObservableCollection<MenuItemModel>(_allMenuItems.Select(m => IsVisibleToUser(m)));