The problem is that I have permissions and not roles.
I have database driven permissions and I get them for each user via logon in the Silverlight application and fill them into a List
. I also have an enumerator for the C# code.
Anyways I do not wish to talk about why I am not using roles etc.
I want to type my permission into XAML elements and set Vi开发者_JAVA技巧sibility and IsEnabled on them.
Like this:
<Button IsEnabled="{Binding IsAdmin}" />
First the Attached dependency property:
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
}
}
The XAML namespace code:
xmlns:permissions="clr-namespace:SL.Permissions"
The button in XAML:
<Button Content="Save" permissions:Permission.IsEnabled="ADMIN,EDITOR" Command={Binding SaveClickCommand} />
So this button will be enabled only for users with ADMIN or EDITOR permissions
<Button Content="Save" permissions:Permission.Visibility="ADMIN" Command={Binding SaveClickCommand} />
This button will be visible only for user with ADMIN permissions
Of course you are not limited to use this only with buttons.
I am open for any code optimization comments or comments in general about this solution.
TODO: you will have to implement your own method to check if the user has permissions
I did that with my method hasPermission = HasUserPermission(permission);
which looks up the enumrable permission in the List
of permissions I get for the user via logon.
What I miss: The perfect solution for this would be intellisense for all the permissions in XAML, but since I want to set more than one permission it's kind of useless.
If you want to use only one permission and want intellisense to show you the permissions you can use, just change the attached dependency property to this (example for Visibility, you'll have to do the same for IsEnabled):
public static readonly DependencyProperty VisibilityProperty =
DependencyProperty.RegisterAttached("Visibility", typeof(EnumPermission), typeof(Permission), new PropertyMetadata(Visibility_Callback));
I have set the second parameter (Type propertyType
) to EnumPermission
instead of string
, that will enable intellisense in XAML to show you permissions from your enumerator.
精彩评论