具有可见性权限的WPF菜单

时间:2015-06-18 07:26:17

标签: c# wpf

我是一个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; }
}

具体来说,我所做的是处理每个子节点然后如果可见我将它添加到集合中......你看到任何可能更好的解决方案吗?

由于

1 个答案:

答案 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