1

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

    }
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 回答