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

Product Version 2018.3 911
Product RadTreeView for WinForms

ToggleStateConverter

RadTreeView allows binding the check boxes to a custom property from the associated data object by specifying the RadTreeView.CheckedMember property. A common case is when the specified CheckedMember is a property of custom type and it should be converted to ToggleState which is required by the check boxes in the tree view. This article demonstrates how you can modify the way a property is being displayed and edited by using custom TypeConverters. A Type Converter is used to convert values between data types. Here are the four main methods that are usually used when implementing a custom Type Converter.

  • Override the CanConvertFrom method that specifies which type the converter can convert from.

  • Override the ConvertFrom method that implements the conversion.

  • Override the CanConvertTo method that specifies which type the converter can convert to.

  • Override the ConvertTo method that implements the conversion.

Consider the RadTreeView is populated with Item objects having the following properties:

Item class

public class Item : System.ComponentModel.INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    int m_id;
    int m_parentId;
    string m_name;
    string m_isActive;
    public Item(string name, string isActive, int parent_Id, int id)
    {
        this.m_name = name;
        this.m_isActive = isActive;
        this.m_parentId = parent_Id;
        this.m_id = id;
    }
    public int Id
    {
        get
        {
            return m_id;
        }
        set
        {
            if (this.m_id != value)
            {
                this.m_id = value;
                OnPropertyChanged("Id");
            }
        }
    }
    public int ParentId
    {
        get
        {
            return m_parentId;
        }
        set
        {
            if (this.m_parentId != value)
            {
                this.m_parentId = value;
                OnPropertyChanged("ParentId");
            }
        }
    }
    public string Name
    {
        get
        {
            return m_name;
        }
        set
        {
            if (this.m_name != value)
            {
                this.m_name = value;
                OnPropertyChanged("Name");
            }
        }
    }
    public string IsActive
    {
        get
        {
            return m_isActive;
        }
        set
        {
            if (this.m_isActive != value)
            {
                this.m_isActive = value;
                OnPropertyChanged("IsActive");
            }
        }
    }
}

Public Class Item
    Implements System.ComponentModel.INotifyPropertyChanged
    Public Event PropertyChanged As PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
    Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub
    Private m_id As Integer
    Private m_parentId As Integer
    Private m_name As String
    Private m_isActive As String
    Public Sub New(ByVal name As String, ByVal isActive As String, ByVal parent_Id As Integer, ByVal id As Integer)
        Me.m_name = name
        Me.m_isActive = isActive
        Me.m_parentId = parent_Id
        Me.m_id = id
    End Sub
    Public Property Id As Integer
        Get
            Return m_id
        End Get
        Set(ByVal value As Integer)
            If Me.m_id <> value Then
                Me.m_id = value
                OnPropertyChanged("Id")
            End If
        End Set
    End Property
    Public Property ParentId As Integer
        Get
            Return m_parentId
        End Get
        Set(ByVal value As Integer)
            If Me.m_parentId <> value Then
                Me.m_parentId = value
                OnPropertyChanged("ParentId")
            End If
        End Set
    End Property
    Public Property Name As String
        Get
            Return m_name
        End Get
        Set(ByVal value As String)
            If Me.m_name <> value Then
                Me.m_name = value
                OnPropertyChanged("Name")
            End If
        End Set
    End Property
    Public Property IsActive As String
        Get
            Return m_isActive
        End Get
        Set(ByVal value As String)
            If Me.m_isActive <> value Then
                Me.m_isActive = value
                OnPropertyChanged("IsActive")
            End If
        End Set
    End Property
End Class

The tree view is populated with data as follows:

Bind RadTreeView

BindingList<Item> items = new BindingList<Item>();
items.Add(new Item(@"C:\", "false", 0, 1));
items.Add(new Item(@"Documents", "false", 1, 2));
items.Add(new Item(@"Program Files (x86)", "false", 1, 3));
items.Add(new Item(@"D:\", "false", 0, 4));
items.Add(new Item(@"Projects", "false", 4, 5));
this.radTreeView1.DisplayMember = "Name";
this.radTreeView1.ChildMember = "Id";
this.radTreeView1.ParentMember = "ParentId";
this.radTreeView1.CheckedMember = "IsActive";
this.radTreeView1.DataSource = items;
this.radTreeView1.CheckBoxes = true;

Dim items As BindingList(Of Item) = New BindingList(Of Item)()
items.Add(New Item("C:\", "false", 0, 1))
items.Add(New Item("Documents", "false", 1, 2))
items.Add(New Item("Program Files (x86)", "false", 1, 3))
items.Add(New Item("D:\", "false", 0, 4))
items.Add(New Item("Projects", "false", 4, 5))
Me.RadTreeView1.DisplayMember = "Name"
Me.RadTreeView1.ChildMember = "Id"
Me.RadTreeView1.ParentMember = "ParentId"
Me.RadTreeView1.CheckedMember = "IsActive"
Me.RadTreeView1.DataSource = items
Me.RadTreeView1.CheckBoxes = True

The specified CheckedMember is the Item.IsActive property which is typeof(string) indicating the "true" / "false" values. In order to convert these string values to a valid ToggleState you need to use a custom Type Converter. The following code snippet illustrates a sample implementation:

Custom TypeConverter's implementation

public class CustomTypeConverter : TypeConverter
{
    public CustomTypeConverter()
    {
    }
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(ToggleState))
        {
            return true;
        }
        return base.CanConvertFrom(context, sourceType);
    }
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if (destinationType == typeof(ToggleState))
        {
            return true;
        }
        return base.CanConvertTo(context, destinationType);
    }
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is ToggleState)
        {
            ToggleState state = (ToggleState)value;
            if (state == ToggleState.On)
            {
                return "true";
            }
            else
            {
                return "false";
            }
        }
        return base.ConvertFrom(context, culture, value);
    }
    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        string v = Convert.ToString(value);
        if (v.ToLower() == "true" || v.ToLower() == "yes" || v.ToLower() == "on")
        {
            return ToggleState.On;
        }
        else if (v.ToLower() == "false" || v.ToLower() == "no" || v.ToLower() == "off")
        {
            return ToggleState.Off;
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

Public Class CustomTypeConverter
    Inherits TypeConverter
    Public Sub New()
    End Sub
    Public Overrides Function CanConvertFrom(ByVal context As ITypeDescriptorContext, ByVal sourceType As Type) As Boolean
        If sourceType = GetType(ToggleState) Then
            Return True
        End If
        Return MyBase.CanConvertFrom(context, sourceType)
    End Function
    Public Overrides Function CanConvertTo(ByVal context As ITypeDescriptorContext, ByVal destinationType As Type) As Boolean
        If destinationType = GetType(ToggleState) Then
            Return True
        End If
        Return MyBase.CanConvertTo(context, destinationType)
    End Function
    Public Overrides Function ConvertFrom(ByVal context As ITypeDescriptorContext, ByVal culture As CultureInfo, ByVal value As Object) As Object
        If TypeOf value Is ToggleState Then
            Dim state As ToggleState = CType(value, ToggleState)
            If state = ToggleState.[On] Then
                Return "true"
            Else
                Return "false"
            End If
        End If
        Return MyBase.ConvertFrom(context, culture, value)
    End Function
    Public Overrides Function ConvertTo(ByVal context As ITypeDescriptorContext, ByVal culture As CultureInfo, ByVal value As Object, ByVal destinationType As Type) As Object
        Dim v As String = Convert.ToString(value)
        If v.ToLower() = "true" OrElse v.ToLower() = "yes" OrElse v.ToLower() = "on" Then
            Return ToggleState.[On]
        ElseIf v.ToLower() = "false" OrElse v.ToLower() = "no" OrElse v.ToLower() = "off" Then
            Return ToggleState.Off
        End If
        Return MyBase.ConvertTo(context, culture, value, destinationType)
    End Function
End Class

Now, you need to apply the custom TypeConverter to the RadTreeView.ToggleStateConverter property:

The property was introduced in R3 2018 (version 2018.3.911).

Set the ToggleStateConverter

this.radTreeView1.ToggleStateConverter = new CustomTypeConverter();

Me.RadTreeView1.ToggleStateConverter = New CustomTypeConverter()

Now, you can toggle/untoggle the nodes and this will be properly reflected to the underlying data object:

WinForms RadTreeView ToggleStateConverter

Note that following this approach it is possible to convert any custom type to ToggleState and thus bind the check boxes in the tree view to any custom property that you have. It is just necessary to implement the specific conversion.

See Also

In this article