New to Telerik UI for WPF? Download free 30-day trial

Property Sets

With the property sets feature RadPropertyGrid enables its users to process multiple items' properties simultaneously. You no longer need to provide additional view models to expose those properties or manage their changes backwards to your business object instances. Everything now happens under the hood.

Property sets do not support nested properties. You need to create a computed property in your business objects pointing to the nested property to enable this functionality. For example, you can define a CountryName property returning the value of the nested Name property of the bound objects' Country.

Setup

In order to benefit from this feature, you should set RadPropertyGrid's PropertySetMode property to an appropriate value and provide an IEnumerable instance that contains the business objects.

For the means of illustrating the separate mode values, the following types will be used:

Example 1: Preparing sample data

public class Ellipse 
{ 
    public Color FillColor { get; set; } 
    public double RadiusX1 { get; set; } 
    public double RadiusX2 { get; set; } 
    public Point Center { get; set; } 
} 
 
public class RegularPolygon 
{ 
    public int CornersCount { get; set; } 
    public Color FillColor { get; set; } 
    public Point Center { get; set; } 
    public double SideLength { get; set; } 
} 
 
public class ViewModel 
{ 
    public IEnumerable<object> Shapes 
    { 
        get 
        { 
            return new List<object>() 
            { 
                new Ellipse() 
                { 
                    Center = new Point(1,1), 
                    FillColor = Colors.Red, 
                    RadiusX1 = 4, RadiusX2 = 2 
                    }, 
                    new RegularPolygon() 
                { 
                    Center = new Point(3,2), 
                    FillColor = Colors.Blue, 
                    CornersCount = 3, 
                    SideLength = 10 
                } 
            }; 
        } 
    } 
} 
Public Class Ellipse 
    Public Property FillColor() As Color 
    Public Property RadiusX1() As Double 
    Public Property RadiusX2() As Double 
    Public Property Center() As Point 
End Class 
 
Public Class RegularPolygon 
    Public Property CornersCount() As Integer 
    Public Property FillColor() As Color 
    Public Property Center() As Point 
    Public Property SideLength() As Double 
End Class 
 
Public Class ViewModel 
    Public ReadOnly Property Shapes() As IEnumerable(Of Object) 
        Get 
            Return New List(Of Object)() From { 
                New Ellipse() With { 
                    .Center = New Point(1, 1), 
                    .FillColor = Colors.Red, 
                    .RadiusX1 = 4, 
                    .RadiusX2 = 2 
                }, 
                New RegularPolygon() With { 
                    .Center = New Point(3, 2), 
                    .FillColor = Colors.Blue, 
                    .CornersCount = 3, 
                    .SideLength = 10 
                } 
            } 
        End Get 
    End Property 
End Class 

Example 2: Defining RadPropertyGrid

<Grid> 
    <Grid.Resources> 
        <local:ViewModel x:Key="ViewModel" /> 
    </Grid.Resources> 
    <telerik:RadPropertyGrid DataContext="{StaticResource ViewModel}" Item="{Binding Shapes}" /> 
</Grid> 

Property Set Modes

The PropertySetMode property accepts values of type PropertySetOperation which is an enumeration that has three values - None, Union and Intersection.

None

None is the default value of RadPropertyGrid’s PropertySetMode property. In this case the item value is processed as a single object, regardless of its type. It is a List of objects instance in our occasion.

Figure 1: RadPropertyGrid with PropertySetMode set to None

RadPropertyGrid with PropertySetMode set to None

Both RegularPolygon and Ellipse's properties have been disregarded and only the two public properties of the List class are displayed.

Union

When Union is the active mode, a union set of the items' properties is constructed. In case that a property that is common for several items has the same value for each of them, RadPropertyGrid displays this value in the respective editor. On the other hand, if it has different values for the separate items, the editor displays either null, or the default value for this type.

Figure 2: RadPropertyGrid with PropertySetMode set to Union

RadPropertyGrid with PropertySetMode set to Union

Notice that all 6 distinct properties are displayed.

Intersection

The Intersection mode works in a similar way to the "Union" mode, however, in this case RadPropertyGrid constructs an intersection set instead. Here is the output when "Intersection" mode is applied over the same data source:

Figure 3: RadPropertyGrid with PropertySetMode set to Intersection

RadPropertyGrid with PropertySetMode set to Intersection

In this case, only the Center and FillColor properties which are common for both classes are displayed.

PropertySet Property

As of R3 2017, RadPropertyGrid exposes a PropertySet property of type PropertySet which is a basic implementation of the DynamicObject class. Thus, you can access and modify each of the properties of the set through its indexer.

More information about the DynamicObject class can be found in this MSDN article.

Example 3: Update PropertySet value

    this.RadPropertyGrid.PropertySet["FillColor"] = Colors.Blue; 
    Me.RadPropertyGrid.PropertySet("FillColor") = Colors.Blue 

The control also provides an UpdatePropertySetValue which accepts three arguments:

  • propertyName: The name of the updated property
  • propertyValue: The value of the updated property
  • shouldUpdateBoundData: Indicates whether the bound data (item) should be updated

Example 4 demonstrates how to update the property set similarly to Example 3 but without propagating the changed values back to the underlying models.

Example 4: Update PropertySet value without notifying underlying models

    this.RadPropertyGrid.UpdatePropertySetValue("FillColor", Colors.Blue, false); 
    Me.RadPropertyGrid.UpdatePropertySetValue("FillColor", Colors.Blue, False) 

You can check the Validating Property Sets section from the control's Validation article for information on how to apply validation for property sets.

Customizing PropertyDefinitions

When RadPropertyGrid's PropertySetMode is set to Union or Intersection, the DataContext of the created editors is an instance of PropertySetViewModel. It exposes the CurrentPropertySet property which is the same instance provided by the PropertySet property of the RadPropertyGrid control. You can use this to define your customized property definitions. However, as dynamic properties do not contain any information about their underlying type, an IValueConverter might be needed in certain scenarios.

Examples 5-7 demonstrate how to use a custom EditorTemplate for the integer property of a property set.

Example 5: Defining editor template

<Grid x:Name="LayoutRoot"> 
    <Grid.Resources> 
        <local:ViewModel x:Key="vm" /> 
        <local:MyConverter x:Key="cnv" /> 
        <DataTemplate x:Key="editorTemplate"> 
            <telerik:RadNumericUpDown Value="{Binding CurrentPropertySet[CornersCount], Mode=TwoWay, Converter={StaticResource cnv}}" /> 
        </DataTemplate> 
    </Grid.Resources> 
    <telerik:RadPropertyGrid DataContext="{StaticResource vm}"  
                         Item="{Binding Shapes}"  
                         PropertySetMode="Union"  
                         AutoGeneratingPropertyDefinition="RadPropertyGrid_AutoGeneratingPropertyDefinition"/> 
</Grid> 

Example 6: Setting EditorTemplate of a PropertyDefinition

private void RadPropertyGrid_AutoGeneratingPropertyDefinition(object sender, Telerik.Windows.Controls.Data.PropertyGrid.AutoGeneratingPropertyDefinitionEventArgs e) 
{ 
    if (e.PropertyDefinition.DisplayName == "CornersCount") 
    { 
        e.PropertyDefinition.EditorTemplate = LayoutRoot.Resources["editorTemplate"] as DataTemplate; 
    } 
} 
Private Sub RadPropertyGrid_AutoGeneratingPropertyDefinition(sender As Object, e As Telerik.Windows.Controls.Data.PropertyGrid.AutoGeneratingPropertyDefinitionEventArgs) 
    If e.PropertyDefinition.DisplayName = "CornersCount" Then 
        e.PropertyDefinition.EditorTemplate = TryCast(LayoutRoot.Resources("editorTemplate"), DataTemplate) 
    End If 
End Sub 

Example 7: Defining IValueConverter

public class MyConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
        return Int32.Parse(value.ToString()); 
    } 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
        return value; 
    } 
} 
Public Class MyConverter 
    Implements IValueConverter 
    Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert 
        Return Int32.Parse(value.ToString()) 
    End Function 
    Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack 
        Return value 
    End Function 
End Class 

Figure 4: RadNumericUpDown for integer property of property set

RadNumericUpDown for integer property of property set

Disable creating object instance for null value

By default, RadPropertyGrid will create an object instance for a property of custom data type with null value. This behavior can be altered through the ShouldAddNullForNonMatchingValues boolean property. Its default value is False. When set to True, the control will not create a new instance for null property values.

Example 8: Setting the ShouldAddNullForNonMatchingValues property to True

      <telerik:RadPropertyGrid DataContext="{StaticResource vm}" 
                                 Item="{Binding Shapes}" 
                                 PropertySetMode="Union" 
                                 telerik:PropertySet.ShouldAddNullForNonMatchingValues="True"/> 

See Also

In this article