Enumeration binding to a Combobox

5 posts, 1 answers
  1. Pinho
    Pinho avatar
    39 posts
    Member since:
    Mar 2009

    Posted 24 Mar 2009 Link to this post

    Hi,

     I've got a combobox that I will fill with the items set in an enumeration. To do this I'm using a helper:

     Copying and pasting the example in the page: Missing Enum.GetValues() when doing Silverlight for instance ?

     

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.Reflection;

        /// 
    <summary> 
        /// Helper class to allow users to get the values of a enumeration 
        /// </summary> 
        public static class EnumHelper 
        { 
            /// <summary> 
            /// Get values of an enumeration of type T 
            /// </summary> 
            /// <typeparam name="T">Enumeration type</typeparam> 
            /// <returns>List of types in a enumeration</returns> 
            public static T[] GetValues<T>() 
            { 
                Type enumType = typeof(T); 
     
                if (!enumType.IsEnum) 
                { 
                    throw new ArgumentException("Type '" + enumType.Name + "' is not an enum"); 
                } 
     
                List<T> values = new List<T>(); 
     
                var fields = from field in enumType.GetFields() 
                             where field.IsLiteral 
                             select field; 
     
                foreach (FieldInfo field in fields) 
                { 
                    object value = field.GetValue(enumType); 
                    values.Add((T)value); 
                } 
     
                return values.ToArray(); 
            } 
     
            /// <summary> 
            /// Get all the values of an enumeration of Type enumType 
            /// </summary> 
            /// <param name="enumType">Enumeration type</param> 
            /// <returns>Array of objects</returns> 
            public static object[] GetValues(Type enumType) 
            { 
                if (!enumType.IsEnum) 
                { 
                    throw new ArgumentException("Type '" + enumType.Name + "' is not an enum"); 
                } 
     
                List<object> values = new List<object>(); 
     
                var fields = from field in enumType.GetFields() 
                             where field.IsLiteral 
                             select field; 
     
                foreach (FieldInfo field in fields) 
                { 
                    object value = field.GetValue(enumType); 
                    values.Add(value); 
                } 
     
                return values.ToArray(); 
            } 
        } 

    The combo box items appear correctly with the value of the enumerator, but when I select one of its values, instead of the value, I get the index or key :(

     I tried to create a SelectionBoxItemTemplate but when I try to bind it I don't get any value, what am I doing wrong?

    <telerikInput:RadComboBox.SelectionBoxItemTemplate> 
       <DataTemplate> 
         <TextBlock Text="{Binding Path=Value}"/> 
       </DataTemplate> 
    </telerikInput:RadComboBox.SelectionBoxItemTemplate> 

    Thanks to all,

    L. Pinho


  2. Answer
    Miroslav
    Admin
    Miroslav avatar
    922 posts
    Member since:
    Sep 2012

    Posted 24 Mar 2009 Link to this post

    Hi Luis,

    Yes, this is a known issue for the Silverlight ItemsContol and happens in all ItemsControls. It internally converts the enum values to Int values, so you cannot use value converters or appropriate bindings to convert it.

    One way to work around this is to have a custom wrapper class (something like boxing):

    Here is how you can get the values and wrap them:

    var enumType = typeof(HorizontalAlignment);  
     
    var fields = from field in enumType.GetFields(BindingFlags.Static | BindingFlags.Public)  
                 select new EnumViewModel(field.GetValue(null));  
     
    comboBox.ItemsSource = fields;  
     

    And the helper class:

    public class EnumViewModel  
    {  
        public EnumViewModel(object value)  
        {  
            this.EnumValue = value;  
            this.Name = value.ToString();  
        }  
     
        public object EnumValue  
        {  
            get;  
            set;  
        }  
     
        public String Name  
        {  
            get;  
            private set;  
        }  
     
        public override bool Equals(object obj)  
        {  
            return EnumValue.Equals(obj);  
        }  
     
        public override int GetHashCode()  
        {  
            return EnumValue.GetHashCode();  
        }  

    Also if you are binding to a ViewModel that exposes a property with an enum value, you can implement a ValueConverter that will convert between the wrapper and the enum values. (You need the equals override for SelectedItem property to work)

    Greetings,
    Miroslav
    the Telerik team

    Check out Telerik Trainer , the state of the art learning tool for Telerik products.

  3. Pinho
    Pinho avatar
    39 posts
    Member since:
    Mar 2009

    Posted 26 Mar 2009 Link to this post

    Hi Miroslav,

     thanks for the reply, after a few problems in the beggining I adapted some of your code and hints, and manage to do a "universal" class than I can use for all the enumerations without having to change the enumeration definition.

     If it helps anyone, I'm sharing the code:

        /// <summary> 
        /// Helper class to allow users to get the values of a enumeration 
        /// </summary> 
        public static class EnumHelper 
        { 
            /// <summary> 
            /// Get values of an enumeration of type T 
            /// </summary> 
            /// <typeparam name="T">Enumeration type</typeparam> 
            /// <returns>List of types in a enumeration</returns> 
            public static T[] GetValues<T>() 
            { 
                Type enumType = typeof(T); 
     
                if (!enumType.IsEnum) 
                { 
                    throw new ArgumentException("Type '" + enumType.Name + "' is not an enum"); 
                } 
     
                List<T> values = new List<T>(); 
     
                var fields = from field in enumType.GetFields() 
                             where field.IsLiteral 
                             select field; 
     
                foreach (FieldInfo field in fields) 
                { 
                    object value = field.GetValue(enumType); 
                    values.Add((T)value); 
                } 
     
                return values.ToArray(); 
            } 
     
            /// <summary> 
            /// Get all the values of an enumeration of Type enumType 
            /// </summary> 
            /// <param name="enumType">Enumeration type</param> 
            /// <returns>Array of objects</returns> 
            public static object[] GetValues(Type enumType) 
            { 
                if (!enumType.IsEnum) 
                { 
                    throw new ArgumentException("Type '" + enumType.Name + "' is not an enum"); 
                } 
     
                List<object> values = new List<object>(); 
     
                var fields = from field in enumType.GetFields() 
                             where field.IsLiteral 
                             select field; 
     
                foreach (FieldInfo field in fields) 
                { 
                    object value = field.GetValue(enumType); 
                    values.Add(value); 
                } 
     
                return values.ToArray(); 
            } 
     
            /// <summary> 
            /// Get a list of items inside a enumeration 
            /// </summary> 
            /// <param name="enumType">The enumeration type</param> 
            /// <returns>List of items Index, Value</returns> 
            public static List<EnumHelperItem> GetListOfItems(Type enumType) 
            { 
                List<EnumHelperItem> output = new List<EnumHelperItem>(); 
                if (!enumType.IsEnum) 
                { 
                    throw new ArgumentException("Type '" + enumType.Name + "' is not an enum"); 
                } 
     
                var fields = from field in enumType.GetFields() 
                             where field.IsLiteral 
                             select field; 
     
                int i=0
                foreach (FieldInfo field in fields) 
                { 
                    object value = field.GetValue(enumType); 
                    output.Add(new EnumHelperItem(i, value)); 
                    i++; 
                } 
     
                return output; 
            } 
     
        } 
     
        /// <summary> 
        /// Item helper 
        /// </summary> 
        public class EnumHelperItem : IValueConverter 
        { 
            int index; 
     
            /// <summary> 
            /// Index of the enumerator item 
            /// </summary> 
            public int Index 
            { 
                get { return index; } 
                set { index = value; } 
            } 
            object value; 
     
            /// <summary> 
            /// Value of the enumerator item 
            /// </summary> 
            public object Value 
            { 
                get { return this.value; } 
                set { this.value = value; } 
            } 
     
            /// <summary> 
            /// Default constructor 
            /// </summary> 
            public EnumHelperItem() 
            { } 
     
            /// <summary> 
            /// EnumHelperItem constructor 
            /// </summary> 
            /// <param name="index"></param> 
            /// <param name="value"></param> 
            public EnumHelperItem(int index, object value) 
            { 
                Index = index
                Value = value
            } 
     
            #region IValueConverter Members 
            /// <summary> 
            ///  
            /// </summary> 
            /// <param name="value"></param> 
            /// <param name="targetType"></param> 
            /// <param name="parameter"></param> 
            /// <param name="culture"></param> 
            /// <returns></returns
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
            { 
                return value.ToString(); 
                //return ((EnumHelperItem)value).Value.ToString(); 
            } 
     
            /// <summary> 
            ///  
            /// </summary> 
            /// <param name="value"></param> 
            /// <param name="targetType"></param> 
            /// <param name="parameter"></param> 
            /// <param name="culture"></param> 
            /// <returns></returns
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
            { 
                return Enum.Parse(targetType,((EnumHelperItem)value).Value.ToString(), false); 
            } 
            /// <summary> 
            ///  
            /// </summary> 
            /// <param name="obj"></param> 
            /// <returns></returns
            public override bool Equals(object obj) 
            { 
                if (this.Value != null && obj != null) 
                    if (obj.GetType() == typeof(string)) 
                        return obj.ToString().Equals(this.Value.ToString()); 
                    else if (obj.GetType() == typeof(EnumHelperItem)) 
                        return ((EnumHelperItem)obj).Value.ToString().Equals(this.Value.ToString()); 
                    else 
                        return false; 
                else 
                    return false; 
            } 
     
            /// <summary> 
            ///  
            /// </summary> 
            /// <returns></returns
            public override int GetHashCode() 
            { 
                return base.GetHashCode(); 
            } 
            #endregion 
        } 

    The initial part of the code was retrieved from the site: Missing enum get values...

    Usage example:

        <UserControl.Resources> 
            <ResourceDictionary> 
                <presutils:EnumHelperItem x:Key="EnumConverter"/> 
            </ResourceDictionary> 
        </UserControl.Resources> 
     
    <telerikInput:RadComboBox x:Name="CmbStatus" SelectedItem="{Binding Path=BindProp, Mode=TwoWay, Converter={StaticResource EnumConverter}}"
                <telerikInput:RadComboBox.ItemTemplate> 
                    <DataTemplate> 
                        <TextBlock Text="{Binding Path=Value}"></TextBlock> 
                    </DataTemplate> 
                </telerikInput:RadComboBox.ItemTemplate> 
            </telerikInput:RadComboBox > 

    List<EnumHelperItem> listOfEnumerations = EnumHelper.GetListOfItems(typeof(MyEnumeration)); 
    CmbStatus.ItemsSource = listOfEnumerations

    Thanks again and best regards,

    L.Pinho



  4. Riccardo
    Riccardo avatar
    36 posts
    Member since:
    Apr 2009

    Posted 09 Nov 2009 Link to this post

    If you don't want to use linq you can use this code:

    public static T[] GetValues<T>()  
            {  
                Type enumType = typeof(T);  
     
                if (!enumType.IsEnum)  
                {  
                    throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");  
                }  
     
                List<T> values = new List<T>();  
     
                FieldInfo[] fields = enumType.GetFields();  
     
                foreach (FieldInfo field in fields)  
                {  
                    if (field.IsLiteral)  
                    {  
                        object value = field.GetValue(enumType);  
                        values.Add((T)value);  
                    }  
                }  
     
                return values.ToArray();  
            } 

  5. Usame Esendir
    Usame  Esendir avatar
    8 posts
    Member since:
    Feb 2010

    Posted 01 Mar 2010 Link to this post

    If you are using int value for binding it gives error, to solve the problem make sure your enum values are from 0 to n.
    And then apply the following;

    <telerik:RadComboBox x:Name="cmbVideoType" SelectedIndex="{Binding Type}" DisplayMemberPath="Value" /> 

    List<EnumHelperItem> videoTypes = EnumHelper.GetListOfItems(typeof(VideoTypes));  
    cmbVideoType.ItemsSource = videoTypes; 

    Don't forget that Type binding is an integer value and your enum values must be from 0 to n, this is because of Index values of a container is from 0 to n.

    Hope it helps.

Back to Top