使用 VS2008,Silverlight 4。
我创建了一个 AttachedProperty,“RequiresRole”,我在我的 XAML 中设置它。如果用户不在该属性定义的角色中,则将所述控件的可见性设置为折叠。
我目前遇到的问题是“UserHasRole”检查(在我的授权类中,作为RequiredRole_Callback 函数的一部分)在我加载应用程序时触发,但在我有机会登录、验证和设置角色之前为用户。所以该属性正在工作,因为菜单项不可见,但在身份验证后,它当前没有提醒我的 UI 角色已更改。我知道在哪里实施它,只是不知道如何实施。INotifyPropertyChanged?不知道那会怎样。
我的 App.xaml.cs 中有一些属性,“IsAuthenticated”,当用户登录时设置为 true(使用服务调用 SPROC),以及“Role”,这是成功的返回值调用登录 SPROC。
相关Authorization.cs代码:
public static readonly DependencyProperty RequiredRoleProperty = DependencyProperty.RegisterAttached(
"RequiredRole",
typeof(string),
typeof(Authorization),
new PropertyMetadata(RequiredRole_Callback));
// This callback will be invoked when some control will receive a value for your 'RequiredRole' property
private static void RequiredRole_Callback(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
var uiElement = (UIElement)source;
RecalculateControlVisibility(uiElement);
// also this class should subscribe somehow to role changes and update all control's visibility after role being changed
}
private static void RecalculateControlVisibility(UIElement control)
{
//Authorization.UserHasRole() - is your code to check roles
if (Authorization.UserHasRole(GetRequiredRole(control)))
control.Visibility = Visibility.Visible;
else
control.Visibility = Visibility.Collapsed;
}
private static Boolean UserHasRole(string role)
{
string Role = App.Role;
if (Role.ToLower() == role.ToLower())
{
return true;
}
return false;
}
相关 MainPage.xaml 代码:
xmlns:s="clr-namespace:TSMVVM.Authorization"
<HyperlinkButton x:Name="lnkLogin"
HorizontalAlignment="Right"
Tag="Login"
Command="{Binding NavigateCommand}"
s:Authorization.RequiredRole="Azdmin"
CommandParameter="{Binding Tag, ElementName=lnkLogin}"
Content="Login" />
相关 Mainpage.xaml.cs 代码:
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (!App.IsAuthenticated)
{
ContentFrame.Navigate(new Uri("Login", UriKind.Relative));
}
}
更新代码 (注意,将 RequiredRole 更改为 RequiresRole) Authorization.cs
public class Authorization
{
#region Attached DP registration
public static string GetRequiresRole(UIElement obj)
{
return (string)obj.GetValue(RequiresRoleProperty);
}
public static void SetRequiresRole(UIElement obj, string value)
{
obj.SetValue(RequiresRoleProperty, value);
}
#endregion
/// Using a DependencyProperty as the backing store for requiresRole. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RequiresRoleProperty = DependencyProperty.RegisterAttached(
"RequiresRole",
typeof(string),
typeof(Authorization),
new PropertyMetadata(RequiresRole_Callback));
// This callback will be invoked when some control will receive a value for your 'RequiredRole' property
private static void RequiresRole_Callback(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
var uiElement = (UIElement)source;
if (App.IsAuthenticated)
{
RecalculateControlVisibility(uiElement);
}
else
{
EventHandler eh = null;
eh = delegate
{
RecalculateControlVisibility(uiElement);
((App)Application.Current).Authenticated -= eh;
};
((App)Application.Current).Authenticated += eh;
}
}
private static void RecalculateControlVisibility(UIElement control)
{
//Authorization.UserHasRole() - is your code to check roles
if (Authorization.UserHasRole(GetRequiresRole(control)))
control.Visibility = Visibility.Visible;
else
control.Visibility = Visibility.Collapsed;
}
private static Boolean UserHasRole(string role)
{
if (App.Role != null)
{
string Role = App.Role[0].ToString();
if (Role.ToLower() == role.ToLower())
{
return true;
}
}
return false;
}
}
应用程序.xaml.cs
private static string _role;
public event EventHandler Authenticated = delegate { };
public static string Role
{
get
{
return _role;
}
set
{
_role = value;
}
}
MainPage.xaml:
<HyperlinkButton x:Name="lnkSiteParameterDefinitions"
Style="{StaticResource LinkStyle}"
Tag="SiteParameterDefinitions"
s:Authorization.RequiresRole="Admin"
Content="Site Parameter Definitions"
Command="{Binding NavigateCommand}"
CommandParameter="{Binding Tag, ElementName=lnkSiteParameterDefinitions}"/>
最后,login.xaml.cs
private void LogonService_LogonCompleted(object sender, TSMVVMLogonSVC.LogonCompletedEventArgs e)
{
ObservableCollection<string> Result = e.Result;
switch (Result[0])
{
case "Logon Failed":
break;
case "Logon Successful":
PageConductor = new Services.PageConductor();
App.CurrentUser = Result[2];
App.Role = Result[1].ToString();
App.IsAuthenticated = true;
Messenger.Default.Send(new TSMVVM.Messages.FrameMessage() { RootFrame = (Frame)this.Parent});
PageConductor.GoToView("Home", "main");
break;
case "Change Password":
break;
}
}