Custom Property Definition in WPF PropertyGrid

7 May 202124 minutes to read

In this section, let us see how to configure properties manually in (xaml or C#) instead of event or attributes.

Define PropertyItem manually

By default, property items of PropertyGrid.SelectedObject are automatically generated in the PropertyGrid control by using the AutoGeneratingPropertyGridItem event. Now, you can restrict the auto generated items and manually define a property items through the XAML by using the PropertyGridItem.

Adding defined PropertyGridItems into PropertyGrid

If you want to load the manually defined property items into the PropertyGrid, add that Items collection property. You can enable it only by setting the AutoGenerateItems property value as false. The default value of AutoGenerateItems property is true.

NOTE

When AutoGenerateItems is false, AutoGeneratingPropertyGridItem event will not be triggered.

In the following example, AutoGeneratingPropertyGridItem event not triggered by disabling the AutoGenerateItems and items which are manually added in the Items collection only loaded in the PropertyGrid.

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

public enum Gender {
    Male,
    Female
}

public class Employee {
    public string Name { get; set; }
    public string ID { get; set; }
    public DateTime DOB { get; set; }
    public Gender Gender { get; set; }
}

public class ViewModel {
    public Object SelectedEmployee { get; set; }
    public ViewModel() {
        SelectedEmployee = new Employee()
        {
            Name = "John",
            ID = "381",
            DOB = new DateTime(1995, 12, 24),
            Gender = Gender.Male
        };
    }
}
<syncfusion:PropertyGrid AutoGenerateItems="False"
                         SelectedObject="{Binding SelectedEmployee}"
                         x:Name="propertyGrid1">
    <syncfusion:PropertyGrid.DataContext>
        <local:ViewModel></local:ViewModel>
    </syncfusion:PropertyGrid.DataContext>
    <syncfusion:PropertyGrid.Items>
        <syncfusion:PropertyGridItem PropertyName="Name"/>
        <syncfusion:PropertyGridItem PropertyName="DOB"/>
    </syncfusion:PropertyGrid.Items>
</syncfusion:PropertyGrid>
propertyGrid1.AutoGenerateItems = false;

propertyGrid1.Items.Add(new PropertyGridItem() { PropertyName = "Name" });
propertyGrid1.Items.Add(new PropertyGridItem() { PropertyName = "DOB" });

PropertyGridItem added manually

NOTE

View Sample in GitHub

Add or remove PropertyItem at runtime

You can manually add or remove the property item at runtime by adding or removing that item from the Items collection property. You can also clear all the property items from the PropertyGrid.

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

public enum Gender {
    Male,
    Female
}

public class Employee {
    public string Name { get; set; }
    public string ID { get; set; }
    public DateTime DOB { get; set; }
    public Gender Gender { get; set; }
}

public class ViewModel {
    public Object SelectedEmployee { get; set; }
    public ViewModel() {
        SelectedEmployee = new Employee()
        {
            Name = "John",
            ID = "381",
            DOB = new DateTime(1995, 12, 24),
            Gender = Gender.Male
        };
    }
}
<syncfusion:PropertyGrid AutoGenerateItems="False"
                         SelectedObject="{Binding SelectedEmployee}"
                         x:Name="propertyGrid1">
    <syncfusion:PropertyGrid.DataContext>
        <local:ViewModel></local:ViewModel>
    </syncfusion:PropertyGrid.DataContext>
    <syncfusion:PropertyGrid.Items>
        <syncfusion:PropertyGridItem PropertyName="Name"/>
        <syncfusion:PropertyGridItem PropertyName="DOB"/>
    </syncfusion:PropertyGrid.Items>
</syncfusion:PropertyGrid>

<StackPanel>
    <Button Name="addItems"
            Click="AddItems_Click"
            Content="Add Items"></Button>
    <Button x:Name="removeItems"
            Click="RemoveItems_Click"
            Content="Remove Items"></Button>
    <Button Name="clearItems"
            Click="ClearItems_Click"
            Content="Clear Items"></Button>
</StackPanel>
propertyGrid1.AutoGenerateItems = false;

propertyGrid1.Items.Add(new PropertyGridItem()
{
    PropertyName = "Name"
});
propertyGrid1.Items.Add(new PropertyGridItem() 
{
    PropertyName = "DOB"
});

addItems.Click += AddItems_Click;
removeItems.Click += RemoveItems_Click;
clearItems.Click += ClearItems_Click;

You can dynamically add the property item as follows,

private void AddItem_Click(object sender, RoutedEventArgs e) {
    propertyGrid1.Items.Add(new PropertyGridItem()
    {
        PropertyName = "Gender"
    });
}

private void RemoveItems_Click(object sender, RoutedEventArgs e) {
    propertyGrid1.Items.RemoveAt(1);
}

private void ClearItems_Click(object sender, RoutedEventArgs e) {
    propertyGrid1.Items.Clear();
}

PropertyGridItem adding and removing at runtime

Custom definition of PropertyItem

You can customize the display name, description, category, nested mode, readonly state and value editor for any property items.

NOTE

View Sample in GitHub

Manually add own value editor and categorize the properties

If you want to add own value editor and categorize the property items manually, use the PropertyGridItem.Editor and PropertyGridItem.CategoryName properties to the required property items.

NOTE

You can refer Create Custom Value Editor page to know more about how to create a own value editors.

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

public class EmailEditor : MaskEditor {
    public EmailEditor() {
        Mask = @"[A-Za-z0-9._%-]+@[A-Za-z0-9]+.[A-Za-z]{2,3}";
    }
}

public enum Gender {
    Male,
    Female
}

public class Employee {
    public string Name { get; set; }
    public string ID { get; set; }
    public DateTime DOB { get; set; }
    public Gender Gender { get; set; }
    public string EmailID { get; set; }
}

public class ViewModel {
    public Object SelectedEmployee { get; set; }
    public ViewModel() {
        SelectedEmployee = new Employee()
        {
            Name = "John",
            ID = "381",
            DOB = new DateTime(1995, 12, 24),
            Gender = Gender.Male,
            EmailID = "john@123.c"
        };
    }
}
<syncfusion:PropertyGrid AutoGenerateItems="False" 
                         EnableGrouping="True"
                         SelectedObject="{Binding SelectedEmployee}"
                         x:Name="propertyGrid1">
    <syncfusion:PropertyGrid.DataContext>
        <local:ViewModel></local:ViewModel>
    </syncfusion:PropertyGrid.DataContext>
    <syncfusion:PropertyGrid.Items>
        <syncfusion:PropertyGridItem PropertyName="Name" 
                                     CategoryName="Basic Info"/>
        <syncfusion:PropertyGridItem PropertyName="ID" 
                                     CategoryName="Basic Info"/>
        <syncfusion:PropertyGridItem PropertyName="DOB"
                                     CategoryName="Basic Info"/>
        <syncfusion:PropertyGridItem PropertyName="Gender" 
                                     CategoryName="Additional Info"/>
        <syncfusion:PropertyGridItem PropertyName="EmailID" 
                                     CategoryName="Additional Info">
            <!--Adding own value editor for the EmailID property-->
            <syncfusion:PropertyGridItem.Editor>
                <local:EmailEditor/>
            </syncfusion:PropertyGridItem.Editor>
        </syncfusion:PropertyGridItem>
    </syncfusion:PropertyGrid.Items>

</syncfusion:PropertyGrid>
propertyGrid1.AutoGenerateItems = false;
propertyGrid1.EnableGrouping = true;

propertyGrid1.Items.Add(new PropertyGridItem()
{
    PropertyName = "Name",
    CategoryName = "Basic Info" 
});
propertyGrid1.Items.Add(new PropertyGridItem() 
{
    PropertyName = "ID", 
    CategoryName = "Birth date of the employee" 
});
propertyGrid1.Items.Add(new PropertyGridItem()
{
    PropertyName = "DOB",
    CategoryName = "Basic Info" 
});
propertyGrid1.Items.Add(new PropertyGridItem()
{
    PropertyName = "Gender",
    CategoryName = "Additional Info" 
});
propertyGrid1.Items.Add(new PropertyGridItem()
{
    PropertyName = "EmailID",
    CategoryName = "Additional Info" 
});

PropertyGridItem category and value editor changed

Here, the masked textbox with email-id mask is assigned as a value editor for the EmailID property and properties are categorized under Basic Info and Additional Info.

NOTE

View Sample in GitHub

Manually define nested properties for PropertyItem

If you want to manually explore only particular nested properties of any property item, add that particular nested properties into the respective property item’s PropertyGridItem.Items collection. You must enable nested property mode by using PropertyGridItem.PropertyExpandMode property value as NestedMode to explore the nested properties. The default value of PropertyGridItem.PropertyExpandMode property is null.

public class Bank {
    public string BankName { get; set; }
    public int CustomerID { get; set; }
    public long AccountNumber { get; set; }
    public override string ToString() {
        return BankName;
    }
}

public class Employee {
    public string ID { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public Bank Bank { get; set; }        
    public DateTime DOB { get; set; }
}

public class ViewModel {
    public Object SelectedEmployee { get; set; }
    public ViewModel() {
        SelectedEmployee = new Employee()
        {
            DOB = new DateTime(1995, 01, 31),
            Name = "Johnson",
            ID = "895",
            Age = 25,
            Bank = new Bank()
            {
                AccountNumber = 123456789,
                CustomerID = 356,
                BankName = "ABC Bank"
            },
        };
    }
}
<syncfusion:PropertyGrid AutoGenerateItems="False" 
                         PropertyExpandMode="NestedMode"
                         SelectedObject="{Binding SelectedEmployee}"
                         x:Name="propertyGrid1">
    <syncfusion:PropertyGrid.DataContext>
        <local:ViewModel></local:ViewModel>
    </syncfusion:PropertyGrid.DataContext>
    <syncfusion:PropertyGrid.Items>
        <syncfusion:PropertyGridItem PropertyName="Name"/>
        <syncfusion:PropertyGridItem PropertyName="ID"/>
        <syncfusion:PropertyGridItem PropertyName="DOB"
                                     NestedPropertyDisplayMode="Show">
            <syncfusion:PropertyGridItem.Items>
                <syncfusion:PropertyGridItem PropertyName="Day"/>
                <syncfusion:PropertyGridItem PropertyName="Month"/>
                <syncfusion:PropertyGridItem PropertyName="Year"/>
            </syncfusion:PropertyGridItem.Items>
        </syncfusion:PropertyGridItem>
    </syncfusion:PropertyGrid.Items>
</syncfusion:PropertyGrid>
propertyGrid1.AutoGenerateItems = false;
propertyGrid1.PropertyExpandMode = PropertyExpandModes.NestedMode;

propertyGrid1.Items.Add(new PropertyGridItem()
{
    PropertyName = "Name"
});
propertyGrid1.Items.Add(new PropertyGridItem() 
{
    PropertyName = "ID"
});

ObservableCollection<PropertyGridItem> DOB_Items = new 
    ObservableCollection<PropertyGridItem>();
DOB_Items.Add(new PropertyGridItem() { PropertyName = "Day" });
DOB_Items.Add(new PropertyGridItem() { PropertyName = "Month" });
DOB_Items.Add(new PropertyGridItem() { PropertyName = "Year" });

propertyGrid1.Items.Add(new PropertyGridItem()
{
    PropertyName = "DOB",
    Items = DOB_Items
});

PropertyGrid displays particular nested properties

NOTE

View Sample in GitHub

Manually customize the UI of description panel

You can customize the different UI for specific property’s description panel by using the PropertyGridItem.DescriptionTemplate property. The DataContext of PropertyGridItem.DescriptionTemplate property is PropertyGridItem.

using System;
using System.ComponentModel;

public enum Gender {
    Male,
    Female
}

public class Employee {
    public string Name { get; set; }
    public string ID { get; set; }
    public DateTime DOB { get; set; }
    public Gender Gender { get; set; }
    public string EmailID { get; set; }
}

public class ViewModel {
    public Object SelectedEmployee { get; set; }
    public ViewModel() {
        SelectedEmployee = new Employee()
        {
            Name = "John",
            ID = "381",
            DOB = new DateTime(1995, 12, 24),
            Gender = Gender.Male,
            EmailID = "john@123.c"
        };
    }
}
<Grid x:Name="grid">
    <Grid.Resources>
        <DataTemplate x:Key="template1">
            <StackPanel>
                <TextBlock 
                    Text="{Binding Name}" 
                    FontSize="16" 
                    Foreground="Red" 
                    TextWrapping="Wrap"/>
                <TextBlock 
                    Text="{Binding Description}"
                    FontSize="14" 
                    Foreground="Green" 
                    TextWrapping="Wrap"/>
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="template2">
            <StackPanel>
                <TextBlock 
                    Text="{Binding Name}" 
                    FontSize="16" 
                    Foreground="BlueViolet" 
                    TextWrapping="Wrap"/>
                <TextBlock 
                    Text="{Binding Description}"
                    FontSize="14" 
                    Foreground="DarkCyan" 
                    TextWrapping="Wrap"/>
            </StackPanel>
        </DataTemplate>
    </Grid.Resources>
    <syncfusion:PropertyGrid
        DescriptionPanelVisibility="Visible"
        AutoGenerateItems="False" 
        x:Name="propertyGrid1">
        <syncfusion:PropertyGrid.SelectedObject>
            <local:Employee></local:Employee>
        </syncfusion:PropertyGrid.SelectedObject>
        <syncfusion:PropertyGrid.Items>
            <syncfusion:PropertyGridItem PropertyName="Name"
                                         Description="Name of the Employee"
                                         DescriptionTemplate="{StaticResource template1}" >
            </syncfusion:PropertyGridItem>
            <syncfusion:PropertyGridItem PropertyName="ID"
                                         Description="ID of the Employee"
                                         DescriptionTemplate="{StaticResource template2}"/>
            <syncfusion:PropertyGridItem PropertyName="DOB"
                                         Description="Date o Birth of the Employee"/>
        </syncfusion:PropertyGrid.Items>
    </syncfusion:PropertyGrid>
</Grid>

PropertyGridItem with different custom description panel

NOTE

View Sample in GitHub