//=====================================================================

        /// <summary>
        /// This is used to recursively add all child properties up to three levels down on reference type
        /// properties to the property collection.
        /// </summary>
        /// <param name="parentProp">The parent property descriptor</param>
        /// <param name="baseName">The base name used as a prefix for child property names</param>
        /// <param name="filter">The attribute filter, if any</param>
        /// <param name="props">The properties to search</param>
        /// <param name="newProps">The list to which new child properties are added</param>
        /// <remarks>To prevent endless recursion and stack overflows, it will only go down three levels.
        /// Properties with a <see cref="BrowsableAttribute"/> set to false are ignored.  Properties with a
        /// <see cref="HidePropertyAttribute"/> are not added to the collection but their children are added.</remarks>
        private void GetChildProperties(PropertyDescriptor parentProp, string baseName, Attribute[] filter,
          PropertyDescriptorCollection props, List<PropertyDescriptor> newProps)
        {
            PropertyDescriptorCollection childProps, otherChildren;
            PropertyDescriptor parent;
            BrowsableAttribute browsable;
            string rootName, childName;

            // Don't go too far down or we could get stuck in an endless loop on properties that contain
            // instances of themselves.
            if(nestingLevel > 2)
                return;

            try
            {
                nestingLevel++;

                foreach(PropertyDescriptor pd in props)
                    if(!pd.PropertyType.IsPrimitive && pd.PropertyType != typeof(string))
                    {
                        // If it's not browsable, ignore it.  We shouldn't have to do this but the initial
                        // collection from GetProperties() (see below) seems to ignore the filter.
                        browsable = (BrowsableAttribute)pd.Attributes[typeof(BrowsableAttribute)];

                        if(browsable != null && !browsable.Browsable)
                            continue;

                        // The browsable filter does work here though
                        childProps = pd.GetChildProperties(filter);

                        // Each child property will be prefixed with the parent property's name separated by an
                        // underscore.  We can't use a period as certain list controls such as ListBox and
                        // ComboBox use the period as a binding path separator.
                        rootName = baseName + pd.Name + "_";

                        foreach(PropertyDescriptor child in childProps)
                        {
                            childName = rootName + child.Name;

                            // If this is a top-level property, the current property descriptor is used.  If it's
                            // a child, we need to wrap it in a ChildPropertyDescriptor.
                            if(parentProp == null)
                                parent = pd;
                            else
                                parent = new ChildPropertyDescriptor(parentProp, pd, rootName);

                            // If hidden, don't add it to the visible properties but do include its children
                            if(child.Attributes[typeof(HidePropertyAttribute)] == null)
                                newProps.Add(new ChildPropertyDescriptor(parent, child, childName));

                            // Get all children of this child property
                            otherChildren = child.GetChildProperties(filter);

                            if(otherChildren.Count > 0)
                                this.GetChildProperties(parent, rootName, filter, otherChildren, newProps);
                        }
                    }
            }
            finally
            {
                nestingLevel--;
            }
        }
Пример #2
0
        //=====================================================================

        /// <summary>
        /// This is used to recursively add all child properties up to three levels down on reference type
        /// properties to the property collection.
        /// </summary>
        /// <param name="parentProp">The parent property descriptor</param>
        /// <param name="baseName">The base name used as a prefix for child property names</param>
        /// <param name="filter">The attribute filter, if any</param>
        /// <param name="props">The properties to search</param>
        /// <param name="newProps">The list to which new child properties are added</param>
        /// <remarks>To prevent endless recursion and stack overflows, it will only go down three levels.
        /// Properties with a <see cref="BrowsableAttribute"/> set to false are ignored.  Properties with a
        /// <see cref="HidePropertyAttribute"/> are not added to the collection but their children are added.</remarks>
        private void GetChildProperties(PropertyDescriptor parentProp, string baseName, Attribute[] filter,
                                        PropertyDescriptorCollection props, List <PropertyDescriptor> newProps)
        {
            PropertyDescriptorCollection childProps, otherChildren;
            PropertyDescriptor           parent;
            BrowsableAttribute           browsable;
            string rootName, childName;

            // Don't go too far down or we could get stuck in an endless loop on properties that contain
            // instances of themselves.
            if (nestingLevel > 2)
            {
                return;
            }

            try
            {
                nestingLevel++;

                foreach (PropertyDescriptor pd in props)
                {
                    if (!pd.PropertyType.IsPrimitive && pd.PropertyType != typeof(string))
                    {
                        // If it's not browsable, ignore it.  We shouldn't have to do this but the initial
                        // collection from GetProperties() (see below) seems to ignore the filter.
                        browsable = (BrowsableAttribute)pd.Attributes[typeof(BrowsableAttribute)];

                        if (browsable != null && !browsable.Browsable)
                        {
                            continue;
                        }

                        // The browsable filter does work here though
                        childProps = pd.GetChildProperties(filter);

                        // Each child property will be prefixed with the parent property's name separated by an
                        // underscore.  We can't use a period as certain list controls such as ListBox and
                        // ComboBox use the period as a binding path separator.
                        rootName = baseName + pd.Name + "_";

                        foreach (PropertyDescriptor child in childProps)
                        {
                            childName = rootName + child.Name;

                            // If this is a top-level property, the current property descriptor is used.  If it's
                            // a child, we need to wrap it in a ChildPropertyDescriptor.
                            if (parentProp == null)
                            {
                                parent = pd;
                            }
                            else
                            {
                                parent = new ChildPropertyDescriptor(parentProp, pd, rootName);
                            }

                            // If hidden, don't add it to the visible properties but do include its children
                            if (child.Attributes[typeof(HidePropertyAttribute)] == null)
                            {
                                newProps.Add(new ChildPropertyDescriptor(parent, child, childName));
                            }

                            // Get all children of this child property
                            otherChildren = child.GetChildProperties(filter);

                            if (otherChildren.Count > 0)
                            {
                                this.GetChildProperties(parent, rootName, filter, otherChildren, newProps);
                            }
                        }
                    }
                }
            }
            finally
            {
                nestingLevel--;
            }
        }