How to manipulate WPF GUI based on user roles

2019-01-22 00:48发布

问题:

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)

回答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();
    }
}


回答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.