1

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

    }
4

1 に答える 1

1

INotifyPropertyChangedこの場合、本当に必要なものではないと思います。アプリケーションが認証されたときに必要なのは、ワンショット イベントだけです。

App クラスに簡単なイベントを追加します。

 public event EventHandler Authenticated = delegate { };

コールバックを変更します:-

private static void RequiredRole_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;
     }
}

イベント ハンドラーが発生した後に削除することは非常に重要であることに注意してください。削除しないと、メモリ リークが発生する可能性があります。

于 2011-02-12T12:38:03.537 に答える