Первое свойство Присоединенная зависимость:
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 показывать вам разрешения от вашего перечислителя.