Edit this page

Bind a RadComboBox to Enum Values

The purpose of this topic is to show you how to build a RadComboBox containing all values of a specific Enum. This is a fairly easy task and can be done in only few steps.

  • The best solution here is to create a view model for the Enum:

public class EnumViewModel
{
    private Type enumType;

    public IEnumerable Values
    {
        get;
        private set;
    }

    [TypeConverter( typeof( TypeTypeConverter ) )]
    public Type EnumType
    {
        get
        {
            return this.enumType;
        }
        set
        {
            this.enumType = value;
            this.InitValues();
        }
    }

    private void InitValues()
    {
        this.Values = this.EnumType.GetFields( System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static )
                        .Select<FieldInfo, object>( ( FieldInfo x ) => x.GetValue( this.EnumType ) );
    }
}
Public Class EnumViewModel
    Private m_enumType As Type

Private _Values As IEnumerable
    Public Property Values() As IEnumerable
        Get
            Return _Values
        End Get
        Private Set(ByVal value As IEnumerable)
            _Values = value
        End Set
    End Property

    <TypeConverter(GetType(TypeTypeConverter))> _
    Public Property EnumType() As Type
        Get
            Return Me.m_enumType
        End Get
        Set(ByVal value As Type)
            Me.m_enumType = value
            Me.InitValues()
        End Set
    End Property

    Private Sub InitValues()
        Me.Values = Me.EnumType.GetFields(System.Reflection.BindingFlags.[Public] Or System.Reflection.BindingFlags.[Static]).Select(Function(ByVal x As FieldInfo) x.GetValue(Me.EnumType))
    End Sub
End Class

The trick here is the TypeConverter attribute on the EnumType property, that allows you to declare the EnumModel in XAML:

<UserControl.Resources>
    <example:EnumViewModel x:Name="DataSource" EnumType="System.Windows.Controls.ClickMode"/>
</UserControl.Resources>

Here is the structure of the TypeTypeConverter class which derives from TypeConverter.

public class TypeTypeConverter : TypeConverter
{
    public override bool CanConvertFrom( ITypeDescriptorContext context, Type sourceType )
    {
        return sourceType.IsAssignableFrom( typeof( string ) );
    }

    public override object ConvertFrom( ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value )
    {
        // Try to load the type from the current assembly (EnumValuesInCombo.dll)
        Type t = Type.GetType( ( string )value, false );
        // If the type is from a different known assembly, try to load it from there
        if ( t == null )
        {
            // Try to load the type from Telerik.Windows.Controls.dll
            t = this.GetTypeFromAssembly( value.ToString(), typeof( Telerik.Windows.Controls.ItemsControl ) );
        }
        if ( t == null )
        {
            // Try to load the type from System.Windows.dll
            t = this.GetTypeFromAssembly( value.ToString(), typeof( System.Windows.Controls.ItemsControl ) );
        }
        // You can also try with other known assemblies.
        //if (t == null)
        //{
        //    t = GetTypeFromAssembly(value.ToString(), typeof(a type that is in the assembly, containing the enum));
        //}
        return t;
    }

    private Type GetTypeFromAssembly( string typeName, Type knownType )
    {
        string assemblyName = knownType.AssemblyQualifiedName;
        return Type.GetType( assemblyName.Replace( knownType.FullName, typeName ), false );
    }
}
Public Class TypeTypeConverter
    Inherits TypeConverter
    Public Overloads Overrides Function CanConvertFrom(ByVal context As ITypeDescriptorContext, ByVal sourceType As Type) As Boolean
        Return sourceType.IsAssignableFrom(GetType(String))
    End Function

    Public Overloads Overrides Function ConvertFrom(ByVal context As ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
        ' Try to load the type from the current assembly (EnumValuesInCombo.dll)
        Dim t As Type = Type.GetType

        ' If the type is from a different known assembly, try to load it from there
        If t Is Nothing Then
            ' Try to load the type from Telerik.Windows.Controls.dll
            t = Me.GetTypeFromAssembly(value.ToString(), GetType(Telerik.Windows.Controls.ItemsControl))
        End If
        If t Is Nothing Then
            ' Try to load the type from System.Windows.dll
            t = Me.GetTypeFromAssembly(value.ToString(), GetType(System.Windows.Controls.ItemsControl))
        End If
        ' You can also try with other known assemblies.
        'if (t == null)
        '{
        '    t = GetTypeFromAssembly(value.ToString(), typeof(a type that is in the assembly, containing the enum));
        '}
        Return t
    End Function

    Private Function GetTypeFromAssembly(ByVal typeName As String, ByVal knownType As Type) As Type
        Dim assemblyName As String = knownType.AssemblyQualifiedName
        Return Type.GetType
    End Function
End Class

Take a closer look at the tricky ConvertFrom() method. It does several things:

  • It tries to load the type from the current assembly.

  • If the type is from a different known assembly, try to load it from there. For example, the method will try to load the enumeration either from Telerik.Windows.Controls.dll or from System.Windows.dll.

  • You can also add code, which tries to load the type from other known assemblies.

There are some limitations in this approach, though – you should modify the TypeTypeConverter class so that it can "recognize" the assemblies that might contain the enumerations, defined in XAML. Of course, if you create the EnumModel in the code-behind you will be able to provide any Enum Type you want – in this case the modifications in the TypeTypeConverter class won't be necessary.

  • The second step is to find your RadComboBox declaration and to set the EnumModel to the ItemsSource property.

<UserControl.Resources>
    <example:EnumViewModel x:Name="DataSource" EnumType="System.Windows.Controls.ClickMode"/>
</UserControl.Resources>
....
<telerik:RadComboBox x:Name="radComboBox"
    ItemsSource="{Binding Source={StaticResource DataSource}, Path=Values}">
</telerik:RadComboBox>
  • The final step is to set the DisplayMemberPath attribute with empty string value. It has to be present, in order for the RadComboBox to be able to properly display its selected item. If you remove it, the control will display the Enum’s integer value in its selection box, instead of its text representation.

<UserControl.Resources>
    <example:EnumViewModel x:Name="DataSource" EnumType="System.Windows.Controls.ClickMode"/>
</UserControl.Resources>
....
<telerik:RadComboBox x:Name="radComboBox"
    ItemsSource="{Binding Source={StaticResource DataSource}, Path=Values}" DisplayMemberPath="">
</telerik:RadComboBox>

The result can be seen on the image below. All members of the System.Windows.Controls.ClickMode enumeration are loaded in the RadComboBox.

See Also