How to manipulate WPF GUI based on user roles

10,640

Solution 1

Although previous answer will work, to me it looks little ugly to detect visibility in logic objects. I would use converter for that...

<Control Visibility={Binding Path=CurrentPrincipal, Converter={StaticResource RoleToVisibilityConverter}, ConverterParameter=Administrator}/>

And then the converter itself

public class RoleToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var principal = value as Principal;
        if(principal != null) {
            return principal.IsInRole((string)parameter) ? Visibility.Visible : Visibility.Collapsed;
        }

        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
         throw new NotImplementedException();
    }
}

Solution 2

<Control Visibility={Binding ElementName=ThisWindow, Path=AdministratorVisibility, Mode=OneWay}/>

In your C# code:

public Visibility AdministratorVisibility
{
    get 
    { 
        MyPrincipal.CurrentPrincipal.IsInRole("Administrator") ? Visibility.Hidden : Visibility.Visible; 
    }
}

You can do the same thing for implementing something for IsReadOnly. If the user's role can change (I'm not sure how these user roles work), you can implement INotifyPropertyChanged and do NotifyPropertyChanged("AdministratorVisibility"), otherwise you could probably change the BindingMode to BindingMode.OneTime and skip implementing the notifications.

This probably isn't a whole lot better than what you're doing already, but it's probably as good as you're going to get.

Share:
10,640
Thies
Author by

Thies

Consultant Love to program agile. C# is preferred language, but anything object oriented will do. Lava Lamps connected to a CI platform is the only way to work...

Updated on June 13, 2022

Comments

  • Thies
    Thies almost 2 years

    I am using .NET's IIdentity and IPrincipal objects for role based security, and I am at the step of modifying controls shown based on roles the current user has.

    My question is what the recommended method is for enabling/disabling fields in a WPF window - showing/hiding fields dependent on IIdentity.IsInRole type calls.

    Can this be done in XAML, or do I have to abstract this into code with what I think is a bit messy in the code behind;

    this.txtUserName.IsReadOnly = !MyPrincipal.CurrentPrincipal.IsInRole("Administrator");
    this.mnuCreateUser.Visibility = MyPrincipal.CurrentPrincipal.IsInRole("Administrator");
     ? Visibility.Hidden : Visibility.Visible;
    

    (Note; my code checks roles when executing functions, what I am looking to do is modifying the GUI dependent on the roles, so users do not see/see readonly elements that they do not have access to)

  • Thies
    Thies almost 15 years
    Thanks for the reply. The roles I am using update only when closing and re-opening the application, so NotifyPropertyChange is not critical. I thought about this method, but was hoping that something more direct existed - sorta like the role attribute syntax one can use on methods.
  • Thies
    Thies almost 15 years
    Ahh, this is very much to my liking. With this in the XAML it should be straight forward to see the access that is required to see the different elements in the GUI. Thank you.
  • SteveCav
    SteveCav almost 14 years
    fellow code swipers, you may need to add "return" before "new NotImplementedException();"
  • Eric
    Eric over 12 years
    I'd probably return either Visibility.Visible at the end or Visibility.Collapsed instead of null depending on whether you want an anonymous user to be able to view the item. (I chose Visibility.Collapsed).
  • noonand
    noonand about 12 years
    I edited the line: var principal = value as Principal; to read: var principal = value as IPrincipal; Also be aware that you will require a reference to System.Security and a "using System.Security.Principal;" statement
  • Adolfo Perez
    Adolfo Perez almost 12 years
    What if multiple Roles have same Visibility settings for a specific control? How could you send multiple ConverterParameters E.g. ConverterParameter=Admin,Developer?
  • PMC
    PMC almost 9 years
    Few years old now but Adolfo Perez I changed the code to have string[] roles = ((string)parameter).Split('|'); return roles.Any(role => principal.IsInRole(role)) ? Visibility.Visible : Visibility.Collapsed;