如果您在视图中经常执行此操作,请考虑使用标记扩展。通常情况下,您不需要从视图或视图模型中获取任何信息来检查用户是否具有正确的声明,这些信息通常在登录时获取,并且不依赖于具体的视图。
public class HasClaimExtension : MarkupExtension {
private readonly string _name;
public HasClaimExtension(string name) {
_name = name;
}
public override object ProvideValue(IServiceProvider serviceProvider) {
return HasClaim();
}
private bool HasClaim() {
if (_name.ToLowerInvariant() == "admin")
return true;
return false;
}
}
然后只需:
<Button IsEnabled="{local:HasClaim Admin}" Height="20" Width="100"/>
如果您真的需要访问您的视图模型,您仍然可以这样做:
在不太可能的情况下,您确实需要访问您的视图模型,您仍然可以这样做:
public class HasClaimExtension : MarkupExtension {
private readonly string _name;
public HasClaimExtension(string name) {
_name = name;
}
public override object ProvideValue(IServiceProvider serviceProvider) {
var service = (IProvideValueTarget) serviceProvider.GetService(typeof (IProvideValueTarget));
var target = service.TargetObject as FrameworkElement;
if (target != null) {
var vm = target.DataContext as MyViewModel;
if (vm != null) {
return vm.HasClaim(_name);
}
}
return false;
}
}
public class MyViewModel {
public bool HasClaim(string claim) {
return false;
}
}
更新以回答您在评论中的问题。您可以像这样做。假设有一个简单的LoginManager类:
public class LoginManager {
public static LoginManager Instance = new LoginManager();
private LoginManager() {
}
public bool IsLoggedIn { get; private set; }
public void Login() {
IsLoggedIn = true;
OnLoggedIn?.Invoke();
}
public bool HasClaim(string name) {
if (!IsLoggedIn)
throw new Exception("Cannot check claim until logged in");
return true;
}
public event Action OnLoggedIn;
}
它有一些指示,用于判断声明是否已经可用,并且还有一个事件来通知当这些声明不可用时它们何时可用。然后在您的标记扩展中,您首先检查声明是否存在。如果是,则立即返回结果。如果没有,则返回false,但订阅当这些声明可用时的事件。之后 - 使用实际值更新目标属性。
public class HasClaimExtension : MarkupExtension {
private readonly string _name;
public HasClaimExtension(string name) {
_name = name;
}
public override object ProvideValue(IServiceProvider serviceProvider) {
if (LoginManager.Instance.IsLoggedIn) {
return LoginManager.Instance.HasClaim(_name);
}
var service = (IProvideValueTarget) serviceProvider.GetService(typeof (IProvideValueTarget));
var target = service.TargetObject as FrameworkElement;
var targetProperty = service.TargetProperty as DependencyProperty;
if (target != null && targetProperty != null) {
if (targetProperty.PropertyType != typeof (bool)) {
throw new Exception("HasClaim extension should be applied to Boolean properties only");
}
LoginManager.Instance.OnLoggedIn += () => {
if (Application.Current.Dispatcher.CheckAccess())
target.SetValue(targetProperty, LoginManager.Instance.HasClaim(_name));
else {
Application.Current.Dispatcher.Invoke(() => {
target.SetValue(targetProperty, LoginManager.Instance.HasClaim(_name));
});
}
};
}
return false;
}
}
HasClaim("NAME")
的属性并将其绑定。 - Mike Zboraypublic string Name { get; set; } public string HasNameClaim { get { return HasClaim(Name); } }
。显然,您需要实现 INPC 以使更新起作用,但我认为您已经明白了这个想法。 - Mike Zboray