Click here to Skip to main content
15,895,746 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Guys, here is a story. The code is a bit simplified not to confuse you
I'm working on an app which will set up UI's behavior and appearance based on user roles. The roles are following:
C#
public enum UserType
    {
        Standard,
        Advanced,
        Admin
    }


I've got a Main Window which hosts a custom control
XAML
<Window x:Class="WPFValidation.MainWindow"
...>
               
    <Grid>
        <WPFValidation:PersonView dp:RoleManager.CurrentRole="Admin" />        
    </Grid>
</Window> 


dp:RoleManager.CurrentRole="Admin"
is an attached Dependency Property which should set User Role to Admin so all nested controls should know that the value of the current user is "Admin" (I'll talk about this DP a bit later)

Here is the code for the PersonView:

XML
<UserControl  x:Class="WPFValidation.PersonView"
...>
    <Grid>
         <Button dp:RoleManager.EnabledRoles="Admin,Advanced" />            
    </Grid>
</UserControl>


which means that only Admin or Advanced users can click this button
(I skip ICommand's implementation and so on to keep the example simple)

And finally, the code for CurrentRole and EnabledRoles DependencyProperties
C#
 public class RoleManager: DependencyObject
    {
                
        public static readonly DependencyProperty CurrentRoleProperty =
            DependencyProperty.RegisterAttached("CurrentRole",
            typeof (UserType), 
            typeof (RoleManager), 
            new FrameworkPropertyMetadata(UserType.Standard,FrameworkPropertyMetadataOptions.Inherits)

        public static void SetCurrentRole (DependencyObject element, UserType value)
        {
            if (element!=null)
                element.SetValue(CurrentRoleProperty, value);
        }

        public static UserType GetCurrentRole (DependencyObject element)
        {
            return element != null ?
                (UserType)element.GetValue(CurrentRoleProperty) 
                : default(UserType);
        }

        public static readonly DependencyProperty EnabledRolesProperty =
            DependencyProperty.RegisterAttached
            ("EnabledRoles", 
            typeof(string), 
            typeof(RoleManager),
            new PropertyMetadata((s, e) => OnEnabledRolesChanged(s)));

        public static void SetEnabledRoles(DependencyObject obj, string value)
        {
            var element = obj as UIElement;
            if (element != null)
                element.SetValue(EnabledRolesProperty, value);
        }

        public static string GetEnabledRolesRoles(DependencyObject obj)
        {
            var element = obj as UIElement;
            return element != null ? (string)obj.GetValue(EnabledRolesProperty) : null;
        }

        public static void OnEnabledRolesChanged(DependencyObject sender)
        {
            var element = sender as UIElement;
            if (element != null)
            {
                var stringRoles = new List<string>(((string)(element.GetValue(EnabledRolesProperty))).Split(','));

//GetEnumFromString is my custom class which converts string to an enum
                List<UserType> roles =
                    stringRoles.Select(p => StringToEnumConverter.GetEnumFromString<UserType>(p.Trim())).ToList();

//Instead of getting a current role from the parent (Admin), it takes a default value (Standard)
                var currentRole = GetCurrentRole(element);
                element.IsEnabled = roles.Contains(currentRole);
            }
        }
        #endregion
    }

So, essentially, the value of the attached DP does not propagate to it's "children".
When I set the CurrentRole for the button explicitly
HTML
<Button dp:RoleManager.CurrentRole="Admin" dp:RoleManager.EnabledRoles="Admin,Advanced" />
, everything worked fine, but it is not what I want. I'd like that attached DP to be set up once at the topmost level, so all the children can use its value.

Any suggestions/ideas/critisism is greatly appreciated
Posted
Updated 18-Oct-12 1:06am
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900