Ejemplo n.º 1
0
        /// <summary>
        /// Creates the property item list.
        /// </summary>
        /// <param name="instance">
        /// The instance.
        /// </param>
        /// <param name="isEnumerable">
        /// if set to <c>true</c> [is enumerable].
        /// </param>
        /// <returns>
        /// A list of <see cref="PropertyItem"/>.
        /// </returns>
        public virtual IList <PropertyItem> CreateItems(object instance, bool isEnumerable)
        {
            if (instance == null)
            {
                return(null);
            }

            var instanceType = instance.GetType();
            var properties   = TypeDescriptor.GetProperties(instance);

            this.PropertyItemFactory.Reset();

            var items = new List <PropertyItem>();

            foreach (PropertyDescriptor pd in properties)
            {
                if (this.ShowDeclaredOnly && pd.ComponentType != instanceType)
                {
                    continue;
                }

                // Skip properties marked with [Browsable(false)]
                if (!pd.IsBrowsable)
                {
                    continue;
                }

                // Read-only properties
                if (!this.ShowReadOnlyProperties && pd.IsReadOnly)
                {
                    continue;
                }

                // If RequiredAttribute is set, skip properties that don't have the given attribute
                if (this.RequiredAttribute != null &&
                    !AttributeHelper.ContainsAttributeOfType(pd.Attributes, this.RequiredAttribute))
                {
                    continue;
                }

                var pi = this.PropertyItemFactory.CreatePropertyItem(pd, instance);
                items.Add(pi);
            }

            return(items.OrderBy(t => t.SortIndex).ToList());
        }
Ejemplo n.º 2
0
        /// <summary>
        ///   This method takes an object Instance and creates the property model.
        ///   The properties are organized in a hierarchy
        ///   PropertyTab
        ///   PropertyCategory
        ///   Property|OptionalProperty|WideProperty|CheckBoxProperty
        /// </summary>
        /// <param name = "instance">
        /// </param>
        /// <param name = "isEnumerable">
        /// </param>
        /// <returns>
        ///   Collection of tab ViewModels
        /// </returns>
        public virtual IList <TabViewModel> CreatePropertyModel(object instance, bool isEnumerable)
        {
            if (instance == null)
            {
                return(null);
            }

            // find the instance type
            var instanceType = isEnumerable
                                   ? TypeHelper.FindBiggestCommonType(instance as IEnumerable)
                                   : instance.GetType();

            if (instanceType == null)
            {
                return(null);
            }

            // find all properties of the instance type
            var properties = isEnumerable
                                 ? TypeDescriptor.GetProperties(instanceType)
                                 : TypeDescriptor.GetProperties(instance);

            // The GetPropertyModel method does not return properties in a particular order,
            // such as alphabetical or declaration order. Your code must not depend on the
            // order in which properties are returned, because that order varies.
            TabViewModel      currentTabViewModel      = null;
            CategoryViewModel currentCategoryViewModel = null;
            Type currentComponentType = null;

            // Setting the default tab name
            // Use the type name of the Instance as the default tab name
            string tabName = DefaultTabName ?? instanceType.Name;

            // Setting the default category name
            string categoryName = DefaultCategoryName;

            propertyMap.Clear();
            int sortOrder = 0;

            var result = new List <TabViewModel>();

            foreach (PropertyDescriptor descriptor in properties)
            {
                if (descriptor == null)
                {
                    continue;
                }

                // TODO: should not show attached dependency properties?
                if (DeclaredOnly && descriptor.ComponentType != instanceType)
                {
                    continue;
                }

                if (descriptor.ComponentType != currentComponentType)
                {
                    categoryName         = DefaultCategoryName;
                    tabName              = DefaultTabName ?? descriptor.ComponentType.Name;
                    currentComponentType = descriptor.ComponentType;
                }

                // Skip properties marked with [Browsable(false)]
                if (!descriptor.IsBrowsable)
                {
                    continue;
                }

                // Read-only properties
                if (!ShowReadOnlyProperties && descriptor.IsReadOnly)
                {
                    continue;
                }

                // If RequiredAttribute is set, skip properties that don't have the given attribute
                if (RequiredAttribute != null &&
                    !AttributeHelper.ContainsAttributeOfType(descriptor.Attributes, RequiredAttribute))
                {
                    continue;
                }

                // The default value for an Enum-property is the first enum in the enumeration.
                // If the first value happens to be filtered due to the attribute [Browsable(false)],
                // the WPF-binding system ends up in an infinite loop when updating the bound value
                // due to a PropertyChanged-call. We must therefore make sure that the initially selected
                // value is one of the allowed values from the filtered enumeration.
                if (descriptor.PropertyType.BaseType == typeof(Enum))
                {
                    List <object> validEnumValues = Enum.GetValues(descriptor.PropertyType).FilterOnBrowsableAttribute();
                    // Check if the enumeration that has all values hidden before accessing the first item.
                    if (validEnumValues.Count > 0 && !validEnumValues.Contains(descriptor.GetValue(instance)))
                    {
                        descriptor.SetValue(instance, validEnumValues[0]);
                    }
                }

                // Create Property ViewModel
                var propertyViewModel = PropertyViewModelFactory.CreateViewModel(instance, descriptor);
                propertyViewModel.IsEnumerable = isEnumerable;
                propertyViewModel.SubscribeValueChanged();

                LocalizePropertyHeader(instanceType, propertyViewModel);
                propertyMap.Add(propertyViewModel.Name, propertyViewModel);
                propertyViewModel.PropertyChanged += OnPropertyChanged;

                if (propertyViewModel.SortOrder == int.MinValue)
                {
                    propertyViewModel.SortOrder = sortOrder;
                }

                sortOrder = propertyViewModel.SortOrder;

                bool categoryFound = ParseTabAndCategory(descriptor, ref tabName, ref categoryName);

                if (!categoryFound && UseDefaultCategoryNameForUncategorizedProperties)
                {
                    categoryName = DefaultCategoryName;
                    tabName      = DefaultTabName ?? descriptor.ComponentType.Name;
                }

                GetOrCreateTab(instanceType, result, tabName, sortOrder, ref currentTabViewModel,
                               ref currentCategoryViewModel);
                GetOrCreateCategory(instanceType, categoryName, sortOrder, currentTabViewModel,
                                    ref currentCategoryViewModel);

                currentCategoryViewModel.Properties.Add(propertyViewModel);
            }

            // Check that properties used as optional properties are not Browsable
            CheckOptionalProperties();

            // Sort the model using a stable sort algorithm
            return(SortPropertyModel(result));
        }