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.

Silverlight RadComboBox Bound to Enum

See Also

In this article