コード例 #1
0
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        /// <summary>
        ///     This method returns an attached property descriptor for the given DP and target type.
        /// </summary>
        internal static DependencyObjectPropertyDescriptor GetAttachedPropertyDescriptor(DependencyProperty dp, Type targetType)
        {
            DependencyObjectPropertyDescriptor dpProp;
            PropertyKey key = new PropertyKey(targetType, dp);

            lock (_propertyMap)
            {
                if (!_propertyMap.TryGetValue(key, out dpProp))
                {
                    dpProp            = new DependencyObjectPropertyDescriptor(dp, targetType);
                    _propertyMap[key] = dpProp;
                }
            }

            return(dpProp);
        }
コード例 #2
0
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------

        #region Constructors

        /// <summary>
        ///     The ctor for this class needs to be public because it is created
        ///     by TypeDescriptor using reflection.
        /// </summary>
        public DependencyObjectProvider() : base(TypeDescriptor.GetProvider(typeof(DependencyObject)))
        {
            // We keep a lot of caches around.  When TypeDescriptor gets a refresh
            // we clear our caches.  We only need to do this if the refresh
            // contains type information, because we only keep static per-type
            // caches.

            TypeDescriptor.Refreshed += delegate(RefreshEventArgs args)
            {
                if (args.TypeChanged != null && typeof(DependencyObject).IsAssignableFrom(args.TypeChanged))
                {
                    ClearCache();
                    DependencyObjectPropertyDescriptor.ClearCache();
                    DPCustomTypeDescriptor.ClearCache();
                    DependencyPropertyDescriptor.ClearCache();
                }
            };
        }
コード例 #3
0
        /// <summary>
        ///     Returns a collection of properties for our object.  We first rely on base
        ///     CLR properties and then we attempt to match these with dependency properties.
        /// </summary>
        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            // Because attached properties can come and go at any time,
            // the set of properties we have here always needs to be rebuilt.

            // We have two code paths here based on filtered attributes.  An attribute
            // filter is just a notificaiton of a filter, it doesn't actually perform
            // the filter.  Because the default PropertyFilterAttribute is PropertyFilter.All,
            // it acts as a nice "don't care" in later filtering stages that TypeDescriptor
            // may apply.  That means that regardless of the filter value, we don't have
            // to fiddle with adding the attribute to the property descriptor.

            PropertyFilterOptions filter = PropertyFilterOptions.Valid | PropertyFilterOptions.SetValues;

            if (attributes != null)
            {
                foreach (Attribute attr in attributes)
                {
                    PropertyFilterAttribute filterAttr = attr as PropertyFilterAttribute;
                    if (filterAttr != null)
                    {
                        filter = filterAttr.Filter;
                        break;
                    }
                }
            }

            if (filter == PropertyFilterOptions.None)
            {
                return(PropertyDescriptorCollection.Empty);
            }

            // First, get the set of all known registered properties in the
            // app domain.  GetRegisteredProperties caches its results and
            // will automatically re-fetch if new properties have been
            // registered
            DependencyProperty[] registeredProperties = GetRegisteredProperties();
            Type instanceType = _instance.GetType();

            // Next, walk through them and see which ones can be attached to this
            // object.  If our filter is specifically SetValues, we can
            // greatly shortcut the entire process by using the local value
            // enumerator.

            List <PropertyDescriptor> filteredProps;

            if (filter == PropertyFilterOptions.SetValues)
            {
                LocalValueEnumerator localEnum = _instance.GetLocalValueEnumerator();
                filteredProps = new List <PropertyDescriptor>(localEnum.Count);

                while (localEnum.MoveNext())
                {
                    DependencyProperty     dp   = localEnum.Current.Property;
                    DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType);

                    // For locally set values, we just want to exclude direct and internal properties.
                    if (!kind.IsDirect && !kind.IsInternal)
                    {
                        DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType);
                        filteredProps.Add(dpProp);
                    }
                }
            }
            else
            {
                filteredProps = new List <PropertyDescriptor>(registeredProperties.Length);

                foreach (DependencyProperty dp in registeredProperties)
                {
                    bool addProp = false;
                    DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType);

                    if (kind.IsAttached)
                    {
                        // Check bit combinations that would yield true in
                        // any case.  For non-attached properties, they're all valid, so if
                        // the valid bit is set, we're done.

                        PropertyFilterOptions anySet   = PropertyFilterOptions.SetValues | PropertyFilterOptions.UnsetValues;
                        PropertyFilterOptions anyValid = PropertyFilterOptions.Valid | PropertyFilterOptions.Invalid;

                        if ((filter & anySet) == anySet || (filter & anyValid) == anyValid)
                        {
                            addProp = true;
                        }

                        if (!addProp && (filter & anyValid) != 0)
                        {
                            bool canAttach = CanAttachProperty(dp, _instance);
                            addProp = canAttach ^ ((filter & anyValid) == PropertyFilterOptions.Invalid);
                        }


                        if (!addProp && (filter & anySet) != 0)
                        {
                            bool shouldSerialize = _instance.ContainsValue(dp);
                            addProp = shouldSerialize ^ ((filter & anySet) == PropertyFilterOptions.UnsetValues);
                        }
                    }
                    else if ((filter & PropertyFilterOptions.SetValues) != 0 && _instance.ContainsValue(dp) && !kind.IsDirect && !kind.IsInternal)
                    {
                        // The property is not attached.  However, it isn't an internal DP and the user
                        // has requested set values.  See if the property is set on the object and include
                        // it if it is.
                        addProp = true;
                    }

                    if (addProp)
                    {
                        DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType);
                        filteredProps.Add(dpProp);
                    }
                }
            }

            PropertyDescriptorCollection properties;

            properties = new PropertyDescriptorCollection(filteredProps.ToArray(), true);
            return(properties);
        }
コード例 #4
0
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods
        
        /// <summary>
        ///     This method returns an attached property descriptor for the given DP and target type.
        /// </summary>
        internal static DependencyObjectPropertyDescriptor GetAttachedPropertyDescriptor(DependencyProperty dp, Type targetType)
        {
            DependencyObjectPropertyDescriptor dpProp;
            PropertyKey key = new PropertyKey(targetType, dp);

            lock(_propertyMap) 
            {
                if (!_propertyMap.TryGetValue(key, out dpProp)) 
                {
                    dpProp = new DependencyObjectPropertyDescriptor(dp, targetType);
                    _propertyMap[key] = dpProp;
                }
            }

            return dpProp;
        }
コード例 #5
0
        //------------------------------------------------------ 
        //
        //  Private Methods 
        // 
        //------------------------------------------------------
 
        #region Private Methods

        //
        // Creates the property descriptor collection for this type.  The return 
        // value is all properties that are exposed on this type.
        // 
        private PropertyDescriptorCollection CreateProperties() 
        {
            PropertyDescriptorCollection baseProps = _parent.GetProperties(); 
            List<PropertyDescriptor> newDescriptors = new List<PropertyDescriptor>(baseProps.Count);

            for (int idx = 0; idx < baseProps.Count; idx++)
            { 
                PropertyDescriptor prop = baseProps[idx];
 
                DependencyObjectPropertyDescriptor dpProp; 
                DependencyProperty dp = null;
 
                bool inMap;

                lock(_propertyMap)
                { 
                    inMap = _propertyMap.TryGetValue(prop, out dpProp);
                } 
 
                if (inMap && dpProp != null)
                { 
                    // We need to verify that this property descriptor contains the correct DP.
                    // We can get the wrong one if a descendant of the type introducing the
                    // CLR property associates a different DP to itself with the same name.
 
                    dp = DependencyProperty.FromName(prop.Name, _objectType);
                    if (dp != dpProp.DependencyProperty) 
                    { 
                        dpProp = null;
                    } 
                    else
                    {
                        // We also need to verify that the property metadata for dpProp matches
                        // our object type's metadata 

                        if (dpProp.Metadata != dp.GetMetadata(_objectType)) 
                        { 
                            dpProp = null;
                        } 
                    }
                }

                if (dpProp == null) 
                {
                    // Either the property wasn't in the map or the one that was in there 
                    // can't work for this type.  Make a new property if this property is 
                    // backed by a DP.  Since we only care about direct dependency properties
                    // we can short circuit FromName for all properties on types that do 
                    // not derive from DependencyObject.  Also, if we already got a DP out of
                    // the map we can skip the dependency object check on the property, since
                    // the fact that we got a dp means that there used to be something in the map
                    // so the component type is already a DependencyObject. 

                    if (dp != null || typeof(DependencyObject).IsAssignableFrom(prop.ComponentType)) 
                    { 
                        if (dp == null)
                        { 
                            dp = DependencyProperty.FromName(prop.Name, _objectType);
                        }

                        if (dp != null) 
                        {
                            dpProp = new DependencyObjectPropertyDescriptor(prop, dp, _objectType); 
                        } 
                    }
 
                    // Now insert the new property in our map.  Note that we will
                    // insert a null value into the map if this property descriptor
                    // had no backing DP so we don't go through this work twice.
 
                    if (!inMap)
                    { 
                        lock(_propertyMap) 
                        {
                            _propertyMap[prop] = dpProp; 
                        }
                    }
                }
 

                // If we found a dependency property desecriptor for this property, 
                // use it as our new property. 

                if (dpProp != null) 
                {
                    prop = dpProp;
                }
 
                newDescriptors.Add(prop);
            } 
 
            return new PropertyDescriptorCollection(newDescriptors.ToArray(), true);
        } 
コード例 #6
0
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------

        #region Private Methods

        //
        // Creates the property descriptor collection for this type.  The return
        // value is all properties that are exposed on this type.
        //
        private PropertyDescriptorCollection CreateProperties()
        {
            PropertyDescriptorCollection baseProps      = _parent.GetProperties();
            List <PropertyDescriptor>    newDescriptors = new List <PropertyDescriptor>(baseProps.Count);

            for (int idx = 0; idx < baseProps.Count; idx++)
            {
                PropertyDescriptor prop = baseProps[idx];

                DependencyObjectPropertyDescriptor dpProp;
                DependencyProperty dp = null;

                bool inMap;

                lock (_propertyMap)
                {
                    inMap = _propertyMap.TryGetValue(prop, out dpProp);
                }

                if (inMap && dpProp != null)
                {
                    // We need to verify that this property descriptor contains the correct DP.
                    // We can get the wrong one if a descendant of the type introducing the
                    // CLR property associates a different DP to itself with the same name.

                    dp = DependencyProperty.FromName(prop.Name, _objectType);
                    if (dp != dpProp.DependencyProperty)
                    {
                        dpProp = null;
                    }
                    else
                    {
                        // We also need to verify that the property metadata for dpProp matches
                        // our object type's metadata

                        if (dpProp.Metadata != dp.GetMetadata(_objectType))
                        {
                            dpProp = null;
                        }
                    }
                }

                if (dpProp == null)
                {
                    // Either the property wasn't in the map or the one that was in there
                    // can't work for this type.  Make a new property if this property is
                    // backed by a DP.  Since we only care about direct dependency properties
                    // we can short circuit FromName for all properties on types that do
                    // not derive from DependencyObject.  Also, if we already got a DP out of
                    // the map we can skip the dependency object check on the property, since
                    // the fact that we got a dp means that there used to be something in the map
                    // so the component type is already a DependencyObject.

                    if (dp != null || typeof(DependencyObject).IsAssignableFrom(prop.ComponentType))
                    {
                        if (dp == null)
                        {
                            dp = DependencyProperty.FromName(prop.Name, _objectType);
                        }

                        if (dp != null)
                        {
                            dpProp = new DependencyObjectPropertyDescriptor(prop, dp, _objectType);
                        }
                    }

                    // Now insert the new property in our map.  Note that we will
                    // insert a null value into the map if this property descriptor
                    // had no backing DP so we don't go through this work twice.

                    if (!inMap)
                    {
                        lock (_propertyMap)
                        {
                            _propertyMap[prop] = dpProp;
                        }
                    }
                }


                // If we found a dependency property desecriptor for this property,
                // use it as our new property.

                if (dpProp != null)
                {
                    prop = dpProp;
                }

                newDescriptors.Add(prop);
            }

            return(new PropertyDescriptorCollection(newDescriptors.ToArray(), true));
        }