PropertyGrid for WPF | ComponentOne
In This Topic
    Nested Properties
    In This Topic

    PropertyGrid allows you to show nested properties by creating a nested property editor. It lets you create a nested property editor with the help of  IPropertyGridEditor interface as described in Custom Editors. The following image displays a nested editor to show nested properties.

    PropertyGrid with nested editor showing nested properties

    To create a nested property editor, create a class that implements the IPropertyGridEditor interface and add an instance of this class to the AvailableEditors collection on the PropertyGrid control as shown in the following code.

    C#
    Copy Code
        public partial class NestedProperties : Window
        {
            public NestedProperties()
            {
                InitializeComponent();
    
                Tag = Properties.Resources.PropertyGridNestedPropertiesDesc;
    
                var nestedPropertyEditor = new NestedPropertyEditor();
    
                // Adding types that are supported by NestedPropertyEditor
                nestedPropertyEditor.SupportedTypes.AddRange(new Type[]
                 {
                   typeof(Owner),
                   typeof(Sales)
                 });
    
                // Adding our custom nested property editor to the C1PropertyGrid's Available editors.
                propertyGrid.AvailableEditors.Add(nestedPropertyEditor);
                InitPropertyGrid();
            }
            private void InitPropertyGrid()
            {
                propertyGrid.SelectedObject = new Company()
                {
                    RegistrationId = "19083",
                    CompanyName = "Microsoft",
                    Owner = new Owner()
                    {
                        Name = "Bill Gates",
                        Gender = "Male",
                        Contact = "+1 983-234-122"
                    },
                    Sales = new Sales()
                    {
                        UnitsSold = 2390000,
                        Revenue = 109000000,
                        Loss = 900000
                    },
                    Departments = new List<Department>()
                    {
                        new Department()
                        {
                            Id = "1",
                            DepartmentName = "Manufacturing",
                            EmployeeCount = 902
                        },
                        new Department()
                        {
                            Id = "2",
                            DepartmentName = "Development",
                            EmployeeCount = 150
                        },
                        new Department()
                        {
                            Id = "3",
                            DepartmentName = "Marketing",
                            EmployeeCount = 1250
                        }
                    }
    
                };
    
            }
        }
    }
    public class NestedPropertyEditor : Expander, IPropertyGridEditor
    {
        private C1PropertyGrid _propertyGrid;
    
        public event PropertyChangedEventHandler ValueChanged;
    
        /// <summary>
        /// Types that are supported by this editor
        /// </summary>
        public List<Type> SupportedTypes { get; set; }
    
        public NestedPropertyEditor()
        {
            SupportedTypes = new List<Type>();
            _propertyGrid = new C1PropertyGrid();
            Content = _propertyGrid;
        }
    
        public void Attach(PropertyAttribute property)
        {
            Header = property.PropertyInfo.PropertyType.Name;
    
            // Binds the internal C1PropertyGrid's SelectedObject with nested property
            Binding binding = new Binding(property.PropertyInfo.Name);
            binding.Source = property.SelectedObject;
            binding.Mode = BindingMode.TwoWay;
            binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            BindingOperations.SetBinding(_propertyGrid, C1PropertyGrid.SelectedObjectProperty, binding);
        }
    
        public IPropertyGridEditor Create()
        {
            return new NestedPropertyEditor();
        }
    
        public void Detach(PropertyAttribute property)
        {
            _propertyGrid.SelectedObject = null;
        }
    
        public bool Supports(PropertyAttribute Property)
        {
            // Checks if the property type is supported by this editor
            return SupportedTypes.Any(x => x == Property.PropertyInfo.PropertyType);
        }
    
        public bool Supports(PropertyInfo property)
        {
            throw new NotImplementedException();
        }
    
        public FrameworkElement Create(C1PropertyGrid parent)
        {
            throw new NotImplementedException();
        }
    
        public void Attach(FrameworkElement editor, PropertyGroup group, Action<FrameworkElement, object> valueChanged)
        {
            throw new NotImplementedException();
        }
    
        public void Detach(FrameworkElement editor)
        {
            throw new NotImplementedException();
        }
    

    In the above example, PropertyGrid is bound to a class, Company, whose properties are displayed in the PropertyGrid control. The following code showcases the Company class and its properties.

    C#
    Copy Code
    public class Company
    {
        public string RegistrationId { get; set; }
        public string CompanyName { get; set; }
        public Owner Owner { get; set; }
        public Sales Sales { get; set; }
        public List<Department> Departments { get; set; }
    }
    
    public class Department
    {
        public string Id { get; set; }
        public string DepartmentName { get; set; }
        public int EmployeeCount { get; set; }
    }
    
    public class Sales
    {
        public double UnitsSold { get; set; }
        public double Revenue { get; set; }
        public double Loss { get; set; }
    }
    
    public class Owner
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public string Contact { get; set; }
    }