Exemple #1
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));
        }
Exemple #2
0
 /// <summary>
 ///   Updates the category (expander/groupbox) header and tooltip
 /// </summary>
 /// <param name = "instanceType">
 /// </param>
 /// <param name = "categoryViewModel">
 /// </param>
 private void LocalizeCategoryHeader(Type instanceType, CategoryViewModel categoryViewModel)
 {
     categoryViewModel.Header  = GetLocalizedString(instanceType, categoryViewModel.Name);
     categoryViewModel.ToolTip = GetLocalizedTooltip(instanceType, categoryViewModel.Name);
 }
Exemple #3
0
        /// <summary>
        ///   The get or create tab.
        /// </summary>
        /// <param name = "instanceType">
        ///   The instance type.
        /// </param>
        /// <param name = "tabs">
        ///   The tabs.
        /// </param>
        /// <param name = "tabName">
        ///   The tab name.
        /// </param>
        /// <param name = "sortOrder">
        ///   The sort order.
        /// </param>
        /// <param name = "currentTabViewModel">
        ///   The current tab view model.
        /// </param>
        /// <param name = "currentCategoryViewModel">
        ///   The current category view model.
        /// </param>
        private void GetOrCreateTab(Type instanceType, ICollection<TabViewModel> tabs, string tabName, int sortOrder,
                                    ref TabViewModel currentTabViewModel, ref CategoryViewModel currentCategoryViewModel)
        {
            if (currentTabViewModel == null || (currentTabViewModel.Name != tabName && ShowTabs))
            {
                currentTabViewModel = tabs.FirstOrDefault(t => t.Name == tabName);

                if (currentTabViewModel == null)
                {
                    // force to find/create a new category as well
                    currentCategoryViewModel = null;
                    currentTabViewModel = CreateTab(tabName);
                    currentTabViewModel.SortOrder = sortOrder;
                    tabs.Add(currentTabViewModel);
                    LocalizeTabHeader(instanceType, currentTabViewModel);
                }
            }
        }
Exemple #4
0
 /// <summary>
 ///   Updates the category (expander/groupbox) header and tooltip
 /// </summary>
 /// <param name = "instanceType">
 /// </param>
 /// <param name = "categoryViewModel">
 /// </param>
 private void LocalizeCategoryHeader(Type instanceType, CategoryViewModel categoryViewModel)
 {
     categoryViewModel.Header = GetLocalizedString(instanceType, categoryViewModel.Name);
     categoryViewModel.ToolTip = GetLocalizedTooltip(instanceType, categoryViewModel.Name);
 }
Exemple #5
0
 /// <summary>
 ///   The get or create category.
 /// </summary>
 /// <param name = "instanceType">
 ///   The instance type.
 /// </param>
 /// <param name = "categoryName">
 ///   The category name.
 /// </param>
 /// <param name = "sortOrder">
 ///   The sort order.
 /// </param>
 /// <param name = "currentTabViewModel">
 ///   The current tab view model.
 /// </param>
 /// <param name = "currentCategoryViewModel">
 ///   The current category view model.
 /// </param>
 private void GetOrCreateCategory(Type instanceType, string categoryName, int sortOrder,
                                  TabViewModel currentTabViewModel,
                                  ref CategoryViewModel currentCategoryViewModel)
 {
     if (currentCategoryViewModel == null || currentCategoryViewModel.Name != categoryName)
     {
         currentCategoryViewModel = currentTabViewModel.Categories.FirstOrDefault(c => c.Name == categoryName);
         if (currentCategoryViewModel == null)
         {
             currentCategoryViewModel = new CategoryViewModel(categoryName, this) { SortOrder = sortOrder };
             currentTabViewModel.Categories.Add(currentCategoryViewModel);
             LocalizeCategoryHeader(instanceType, currentCategoryViewModel);
         }
     }
 }