這更多的是MVVM應用程序設計問題。我試圖實現一個非常基本的基於用戶的權限管理,其中我的應用程序中某些控件的可見性來自當前用戶角色。這裏我簡單的模型:MVVM UI控件依賴用戶使用WPF可見性
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>
現在,這裏我的要求:
- 可見性如此我的UI控件(例如MenuItems)依賴於User.Role。例如:MenuItemA應該是可見的Role.Developer,但不是Role.BusinessAnalyst
- 某些控件可以對多個角色(如開發人員和業務分析師)
我兩個選擇,到目前爲止
可見- 創建一個自定義的轉換器,該轉換器具有根據允許的角色派生Visibility並將其綁定到MenuItem.Visibility Value屬性的邏輯。問題在於:a)允許此控件的角色需要在運行時傳遞,因爲它們來自數據庫,並且不能將CommandParameters綁定到角色集合。 b)轉換器如何訪問User.Role以獲取可見性?
- 在我的UI模型(例如MenuItemModel)中創建屬性內的可見性邏輯。但在這裏我不想創建我的用戶和MenuItemModel類之間的依賴關係。
什麼是最簡潔的方式來派生UI控件基於User.Role動態可見性沒有運行到緊耦合方案(依賴)?
謝謝!
解決方案:所以這就是我最終如何根據@fmunkert的建議來解決它。請注意,我不得不改變MenuItemModel.Items屬性,以訪問「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);
}
這似乎工作正常
有趣的想法@fmunkert,我從來沒有想過這樣的說法,但非常有意義。讓我們看看我得到的其他建議,但到目前爲止,這可能是潛在的答案。謝謝你的幫助 –