Как управлять ролями / разрешениями в XAML с помощью перечислителей - PullRequest
4 голосов
/ 24 августа 2011

Проблема в том, что у меня есть разрешения, а не роли.

У меня есть разрешения на основе базы данных, и я получаю их для каждого пользователя через вход в приложение Silverlight и заполняю их в List.У меня также есть перечислитель для кода C #.

В любом случае я не хочу говорить о том, почему я не использую роли и т. Д.

Я хочу ввести свое разрешение для элементов XAML и установить видимостьи IsEnabled на них.

Как это:

<Button IsEnabled="{Binding IsAdmin}" />

1 Ответ

5 голосов
/ 24 августа 2011

Первое свойство Присоединенная зависимость:

using System;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
//using GalaSoft.MvvmLight; //optional

 namespace SL.Permissions
 {
    public enum EnumPermission : short
    {
        ADMIN = 1,  //Administrator
        EDITOR = 2, //Editor
        USER = 99 //normal user
    }

    public class Permission
    {

        #region private methods

        private static void RecalculateControlVisibility(UIElement control, bool hasPermission)
        {
            if (hasPermission)
                control.Visibility = Visibility.Visible;
            else
                control.Visibility = Visibility.Collapsed;
        }

        private static void RecalculateControlIsEnabled(Control control, bool hasPermission)
        {
            control.IsEnabled = hasPermission;
        }

        #endregion

        #region Visibility

        public static readonly DependencyProperty VisibilityProperty =
            DependencyProperty.RegisterAttached("Visibility", typeof(string), typeof(Permission), new PropertyMetadata(Visibility_Callback));

        private static void Visibility_Callback(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            bool hasPermission = false;

            var uiElement = (UIElement)source;
            var permissions = GetVisibility(uiElement).Split(',');
            EnumPermission permission = new EnumPermission();

            //if using MVVM-light toolkit
            //if (ViewModelBase.IsInDesignModeStatic)
            //{
            //  hasPermission = true;
            //  goto END;
            //}

            //loop trough enumerator
            foreach (var fieldInfo in permission.GetType().GetFields(BindingFlags.Static | BindingFlags.Public))
            {
                //loop trough parameters
                foreach (var item in permissions.Where(m => m.ToUpper() == fieldInfo.Name.ToUpper()))
                {
                    permission = (EnumPermission)Enum.Parse(permission.GetType(), fieldInfo.Name, false);
                    //hasPermission = HasUserPermission(permission); //check if this permission is in users permission list
                    hasPermission = true; //TODO: place here your code to check permission of user
                    if (hasPermission) goto END;
                }
            }

            goto END;

        END:
            RecalculateControlVisibility(uiElement, hasPermission);
        }

        public static void SetVisibility(UIElement element, string value)
        {
            element.SetValue(VisibilityProperty, value);
        }

        public static string GetVisibility(UIElement element)
        {
            return (string)element.GetValue(VisibilityProperty);
        }

        #endregion

        #region IsEnabled

        public static readonly DependencyProperty IsEnabledProperty =
            DependencyProperty.RegisterAttached("IsEnabled", typeof(string), typeof(Permission), new PropertyMetadata(IsEnabled_Callback));

        private static void IsEnabled_Callback(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            bool hasPermission = false;

            var uiElement = (Control)source;
            var permissions = GetIsEnabled(uiElement).Split(',');
            EnumPermission permission = new EnumPermission();

            //if using MVVM-light toolkit
            //if (ViewModelBase.IsInDesignModeStatic)
            //{
            //  hasPermission = true;
            //  goto END;
            //}

            //loop trough enumerator
            foreach (var fieldInfo in permission.GetType().GetFields(BindingFlags.Static | BindingFlags.Public))
            {
                //loop trough parameters
                foreach (var item in permissions.Where(m => m.ToUpper() == fieldInfo.Name.ToUpper()))
                {
                    permission = (EnumPermission)Enum.Parse(permission.GetType(), fieldInfo.Name, false);
                    //hasPermission = HasUserPermission(permission); //check if this permission is in users permission list
                    hasPermission = true; //TODO: place here your code to check permission of user
                    if (hasPermission) goto END;
                }
            }

            goto END;

        END:
            RecalculateControlIsEnabled(uiElement, hasPermission);
        }

        public static void SetIsEnabled(UIElement element, string value)
        {
            element.SetValue(IsEnabledProperty, value);
        }

        public static string GetIsEnabled(UIElement element)
        {
            return (string)element.GetValue(IsEnabledProperty);
        }

        #endregion
    }
}

Код пространства имен XAML:

 xmlns:permissions="clr-namespace:SL.Permissions"

Кнопка в XAML:

<Button Content="Save" permissions:Permission.IsEnabled="ADMIN,EDITOR" Command={Binding SaveClickCommand} />

Таким образом, эта кнопка будет включена только для пользователей с разрешениями ADMIN или EDITOR

<Button Content="Save" permissions:Permission.Visibility="ADMIN" Command={Binding SaveClickCommand} />

Эта кнопка будет видимой только для пользователей с правами ADMIN

Конечно, вы не ограничены использованием только кнопок.

Я открыт для любых комментариев по оптимизации кода или комментариев в целом об этом решении.

TODO: вам придется реализовать ваш собственный метод , чтобы проверить, есть ли у пользователя разрешения

Я сделал это с помощью моего метода hasPermission = HasUserPermission(permission);, который ищет перечисляемое разрешение в List разрешений, которые я получаю для пользователя при входе в систему.

Чего мне не хватает: Идеальным решением для этого будет intellisense для всех разрешений в XAML, но, поскольку я хочу установить более одного разрешения, это бесполезно.

Если вы хотите использовать только одно разрешение и хотите, чтобы intellisense показывал вам разрешения, которые вы можете использовать, просто измените присоединенное свойство зависимости на это (например, для Visibility, вам придется сделать то же самое для IsEnabled):

    public static readonly DependencyProperty VisibilityProperty = 
        DependencyProperty.RegisterAttached("Visibility", typeof(EnumPermission), typeof(Permission), new PropertyMetadata(Visibility_Callback));

Я установил второй параметр (Type propertyType) на EnumPermission вместо string, что позволит intellisense в XAML показывать вам разрешения от вашего перечислителя.

...