我是一个WPF应用程序,它从XML文件加载菜单,每个节点都作为标识用户功能的标记。每个用户都具有与xml文件中定义的标记匹配的可见性权限。我希望在简化代码方面提供一些帮助,因为我非常复杂,从我的观点来看,表现不佳。考虑主菜单由主要项目组成,并且每个主要菜单都包含特定区域功能。如果用户在列表元素处启用,则显示主菜单节点,否则不显示。
public virtual System.Threading.Tasks.Task<MenuItemNode> RegisterMenu(IDictionary<string,Type> functions)
{
var assembly = Assembly.GetCallingAssembly(); //I should get the module that invoked the base class
string filename = GetFullFileName(assembly, MenuFilename);
return Task.Factory.StartNew<MenuItemNode>(() =>
{
string xmlFileName = string.Format(filename);
var doc = new XmlDocument();
using (Stream stream = assembly.GetManifestResourceStream(xmlFileName))
{
if (stream != null)
{
using (var reader = new StreamReader(stream))
{
doc.LoadXml(reader.ReadToEnd());
}
}
}
MenuItemNode menu = BuildMenu(doc.SelectSingleNode(@"/Node"), "/", functions);
return menu;
});
}
private string GetFullFileName(Assembly assembly,string filename)
{
var resourceFiles = assembly.GetManifestResourceNames();
return resourceFiles.First(x => x.EndsWith(filename));
}
private MenuItemNode BuildMenu(XmlNode parent, string path, IDictionary<string, Type> functions)
{
Argument.IsNotNull(() => parent);
if (functions == null || (functions.Count == 0)) return null;
MenuItemNode menuItem = null;
string subPath = "Node";
string name = string.Empty;
string tag = string.Empty;
int position = 0;
bool forceVisible = false;
string parameters = string.Empty;
string group = string.Empty;
bool showInDialog = false;
if (parent.Attributes != null)
{
if (parent.Attributes["name"] != null)
name = parent.Attributes["name"].Value;
if (parent.Attributes["tag"] != null)
tag = parent.Attributes["tag"].Value;
if (parent.Attributes["position"] != null)
position = System.Convert.ToInt32(parent.Attributes["position"].Value);
if (parent.Attributes["force_visible"] != null)
forceVisible = Convert.ToBoolean(parent.Attributes["force_visible"].Value);
if (parent.Attributes["parameters"] != null)
parameters = parent.Attributes["parameters"].Value;
if (parent.Attributes["group"] != null)
group = parent.Attributes["group"].Value;
if (parent.Attributes["showindialog"] != null)
showInDialog = Convert.ToBoolean(parent.Attributes["showindialog"].Value);
}
//parent item
if (string.IsNullOrEmpty(tag))
{
menuItem = CreateMenuItem(name, position);
menuItem.ForceVisible = forceVisible;
// menuItem.Group = group;
}
else//child item
{
if (functions.ContainsKey(tag))
{
menuItem = CreateMenuItem(name, tag, position);
menuItem.ForceVisible = forceVisible;
//menuItem.GroupName = group;
menuItem.ShowInDialog = showInDialog;
//menuItem.MenuParameter = GetMenuItemParameters(parameters);
#region Multiple-tag
if ((functions == null) || !functions.Any()) return null;
#endregion
}
else
{
//todo: add-logging
}
}
if (parent.HasChildNodes)
{
foreach (XmlNode child in parent.SelectNodes(subPath))
{
MenuItemNode childMenuItem = BuildMenu(child, subPath, functions);
if (childMenuItem == null) continue;
int childPosition = childMenuItem.SortIndex;
//This to prevent out-of-boundaries exception
if (childPosition > menuItem.Children.Count)
childPosition = menuItem.Children.Count;
menuItem.Children.Insert(childPosition, childMenuItem);
}
}
return menuItem;
}
private MenuItemNode CreateMenuItem(string text, int position)
{
var item = new MenuItemNode();
item.Text = text;
item.SortIndex = position;
return item;
}
private MenuItemNode CreateMenuItem(string text, string tag, int? position)
{
MenuItemNode item = CreateMenuItem(text, (!position.HasValue) ? 0 : position.Value);
item.FunctionTag = tag;
item.SortIndex = (!position.HasValue) ? 0 : position.Value;
return item;
}
这里是MenuItemNode类
[ContentProperty("Children")]
public class MenuItemNode : INotifyPropertyChanged
{
private string text;
private ICommand command;
private Uri imageSource;
private int sortIndex;
private bool forceVisible;
private bool showInDialog;
private bool isChecked;
public bool IsChecked
{
get
{
return this.isChecked;
}
set
{
if (this.isChecked != value)
{
this.isChecked = value;
this.RaisePropertyChanged(() => this.IsChecked);
}
}
}
public bool IsSeparator { get; set; }
public MenuItemNode()
{
Children = new MenuItemNodeCollection();
SortIndex = 50;
SetCommand();
}
public MenuItemNode(String path)
: base()
{
Path = path;
}
public MenuItemNodeCollection Children { get; private set; }
public virtual ICommand Command
{
get
{
return command;
}
set
{
if (command != value)
{
command = value;
RaisePropertyChanged(() => this.Command);
}
}
}
public Uri ImageSource
{
get
{
return imageSource;
}
set
{
if (imageSource != value)
{
imageSource = value;
RaisePropertyChanged(() => this.ImageSource);
}
}
}
public string Text
{
get
{
return text;
}
set
{
if (text != value)
{
text = value;
RaisePropertyChanged(() => this.Text);
}
}
}
private MenuGroupDescription group;
public MenuGroupDescription Group
{
get { return group; }
set
{
if (group != value)
{
group = value;
RaisePropertyChanged(() => this.Group);
}
}
}
public int SortIndex
{
get
{
return sortIndex;
}
set
{
if (sortIndex != value)
{
sortIndex = value;
RaisePropertyChanged(() => this.SortIndex);
}
}
}
public string Path
{
get;
private set;
}
public bool ForceVisible
{
get
{
return this.forceVisible;
}
set
{
if (forceVisible != value)
{
this.forceVisible = value;
RaisePropertyChanged(() => ForceVisible);
}
}
}
public bool ShowInDialog
{
get
{
return this.showInDialog;
}
set
{
if (showInDialog = value)
{
this.showInDialog = value;
RaisePropertyChanged(() => ShowInDialog);
}
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyExpression.Name));
}
#endregion
protected virtual void SetCommand()
{
this.Command = FunctionMenuCommands.OpenFunctionCommand;
}
public string FunctionTag { get; set; }
}
具体来说,我所做的是处理每个子节点然后如果可见我将它添加到集合中......你看到任何可能更好的解决方案吗?
由于
答案 0 :(得分:0)
谁编写该代码显然不知道如何编写WPF。在WPF中,有一个更简单的选项...只需使用MenuItem.Visibility
属性来隐藏(折叠)用户无权访问的MenuItem
。当然,您需要一些数据绑定安全性bool
属性,然后您可以通过MenuItem.Visibility
将数据绑定到每个MenuItem
的{{1}}属性。这是一个简单的例子:
BooleanToVisibilityConverter
如果特定用户拥有<MenuItem Header="Some option" Visibility="{Binding User.Security.HasSomeOptionPermission,
Converter={StaticResource BooleanToVisibilityConverter}}" ... />
,则会显示SomeOptionPermission
,否则将隐藏该MenuItem
。