I was reading a thread about Commands in the WPF Disciples group and noticed a comment about being unable to initialize an attached property where the type was collection.  The problem was unless you put in an explicit Collection object tag, the property is initialized to null when the XAML parser tries to add to it.  I ran into the same issue when working on VisualStateManager.  This markup failed:

<VisualStateManager.VisualStateGroups>

<VisualStateGroup x:Name="CommonStates">

Because the VisualStateGroups property contained a null collection (not an empty collection) and the XAML parser tried to add it.  This markup worked:

<VisualStateManager.VisualStateGroups>

<VisualStateGroupCollection>

<VisualStateGroup x:Name="CommonStates">

But this seemed inconsistent and unnecessary.  The normal way to do this is to initialize the property in the CLR getter, but attached properties were skipping calling the getter.  This is an optimization:  the XAML parser accesses the DP directly rather than use reflection to find and call the CLR property.  Well, the fix is easy:  hide the DP from the XAML parser, which can be done by using a different name for the registered DP (and making it internal is a good idea), and defining the attached property by using the static getter and setter.  So if the DP is called InternalVisualStateGroups and the getter and setter are for VisualStateGroups, the parser will call the static property.

 

Here's a snippet showing how the property is defined that works:

 

        internal static readonly DependencyProperty VisualStateGroupsProperty =

            DependencyProperty.RegisterAttached("InternalVisualStateGroups",

                            typeof(VisualStateGroupCollection),

                            typeof(VisualStateManager),

                            new UIPropertyMetadata(null,

                                    new PropertyChangedCallback(VisualStateManager.VisualStateGroupsProperty_Changed)));

 

        internal static VisualStateGroupCollection GetVisualStateGroupsInternal(DependencyObject obj)

        {

            if (obj == null)

            {

                throw new ArgumentNullException("obj");

            }

            VisualStateGroupCollection groups = obj.GetValue(VisualStateManager.VisualStateGroupsProperty) as VisualStateGroupCollection;

            if (groups == null)

            {

                groups = new VisualStateGroupCollection();

                SetVisualStateGroups(obj, groups);

            }

            return groups;

        }

 

        public static IList GetVisualStateGroups(DependencyObject obj)

        {

            return VisualStateManager.GetVisualStateGroupsInternal(obj);

        }