Search code examples
silverlightdependency-propertiesattached-properties

Custom XAML property


I've seen a library that allows me to do this inside my XAML, which sets the visibility of the control based on whether or not the user is in a role: s:Authorization.RequiresRole="Admin"

Using that library with my database requires a bunch of coding that I can't really do right now. Ultimately here's what I want to know...

I have received the authenticated users role from my SPROC, and its currently stored in my App.xaml.cs as a property (not necessary for the final solution, just FYI for now). I want to create a property (dependency property? attached property?) that allows me to say something very similar to what the other library has: RequiresRole="Admin", which would collapse the visibility if the user is not in the Admin role. Can anyone point me in the right direction on this?

EDIT After building the authorization class, I get the following error: "The property 'RequiredRole' does not exist on the type 'HyperlinkButton' in the XML Namespace clr-namespace:TSMVVM.Authorization"

I'm trying to add this xaml:

<HyperlinkButton x:Name="lnkSiteParameterDefinitions" 
        Style="{StaticResource LinkStyle}" 
                                  Tag="SiteParameterDefinitions" 
        Content="Site Parameter Definitions" 
        Command="{Binding NavigateCommand}"
        s:Authorization.RequiredRole="Admin"
        CommandParameter="{Binding Tag, ElementName=lnkSiteParameterDefinitions}"/>

When I started typing the s:Authorization.RequiredRole="Admin", intellisense picked it up. I tried setting the typeof(string) and typeof(ownerclass) to HyperlinkButton to see if that would help, but it didn't. Any thoughts?


Solution

  • Attached property is the way to implement it. You should define a property like this:

    public class Authorization
    {
        #region Attached DP registration
    
        public static string GetRequiredRole(UIElement obj)
        {
            return (string)obj.GetValue(RequiredRoleProperty);
        }
    
        public static void SetRequiredRole(UIElement obj, string value)
        {
            obj.SetValue(RequiredRoleProperty, value);
        }
    
        #endregion
    
        // Using a DependencyProperty as the backing store for RequiredRole.  This enables animation, styling, binding, etc...
        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 (Authentication.UserHasRole(GetRequiredRole(control)))
                control.Visibility = Visibility.Visible;
            else 
                control.Visibility = Visibility.Collapsed;
        }
    }
    

    PS: Have noticed too late that you were asking about Silverlight. Though I believe it works in the same way there, but I've tried it only on WPF.