如何根据用户角色控制WPF图形用户界面

10

我正在使用.NET的IIdentity和IPrincipal对象来进行基于角色的安全性,现在我需要根据当前用户所拥有的角色修改显示的控件。

我的问题是,在WPF窗口中启用/禁用字段的推荐方法是什么 - 根据IIdentity.IsInRole类型调用显示/隐藏字段。

这可以在XAML中完成吗,还是我必须将其抽象成一些代码并放到代码后面,这样可能会有些混乱。

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

(注意:我的代码在执行函数时检查角色,我想要做的是根据角色修改GUI,以便用户不会看到/看到他们无权访问的只读元素)

2个回答

22

尽管之前的答案可以工作,但在我的看法中,在逻辑对象中检测可见性有些丑陋。我会使用转换器来解决这个问题...

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

然后是转换器本身

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

啊,这正是我喜欢的。有了这个XAML文件,查看GUI中不同元素所需的访问权限应该会很直观。谢谢。 - Thies
各位代码大佬,你们可能需要在“new NotImplementedException();”之前添加“return”。 - SteveCav
最后我可能会返回Visibility.Visible或者Visibility.Collapsed,而不是null,这取决于你是否希望匿名用户能够查看该项。(我选择了Visibility.Collapsed)。 - Eric
我将代码行:var principal = value as Principal; 修改为:var principal = value as IPrincipal; 另外请注意,您需要引用 System.Security 并添加 "using System.Security.Principal;" 语句。 - noonand
1
如果多个角色针对特定控件具有相同的可见性设置怎么办?你如何发送多个转换器参数,例如 ConverterParameter=Admin,Developer - Adolfo Perez
虽然已经有几年了,但Adolfo Perez改变了代码,使其具有以下功能: string[] roles = ((string)parameter).Split('|'); return roles.Any(role => principal.IsInRole(role)) ? Visibility.Visible : Visibility.Collapsed; - PMC

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

在您的C#代码中:
public Visibility AdministratorVisibility
{
    get 
    { 
        MyPrincipal.CurrentPrincipal.IsInRole("Administrator") ? Visibility.Hidden : Visibility.Visible; 
    }
}

对于实现IsReadOnly,可以采用相同的方法。如果用户角色可能会更改(我不确定这些用户角色是如何工作的),则可以实现INotifyPropertyChanged并执行NotifyPropertyChanged("AdministratorVisibility"),否则你可以将BindingMode更改为BindingMode.OneTime,跳过实现通知。

这可能比您目前正在做的要好得多,但这可能是您能够获得的最好结果。


感谢回复。我使用的角色仅在关闭和重新打开应用程序时更新,因此NotifyPropertyChange并不关键。我考虑过这种方法,但希望存在更直接的方法 - 类似于可以在方法上使用的角色属性语法。 - Thies

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接