VS2008、Silverlight 4 を使用。
XAML で設定する AttachedProperty "RequiresRole" を作成しました。ユーザーがそのプロパティで定義された役割に属していない場合、そのコントロールの可視性は折りたたまれた状態に設定されます。
私が現在抱えている問題は、「UserHasRole」チェック (RequiredRole_Callback 関数の一部としての Authorization クラス内) が、アプリケーションをロードするときに起動することですが、ログイン、認証、およびロールの設定を行う前に発生します。ユーザーのために。メニュー項目が表示されないため、プロパティは機能していますが、現在、認証後にロールが変更されたことを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;
}
}
App.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;
}
}