2

I have a problem binding my WeekDay enum to an combobox. The nutritionPlan binding works great.

Here is my .xaml code:

<Page x:Class="WpfApp.Views.AddDailyNutritionPlan"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:local="clr-namespace:WpfApp.Views"
  mc:Ignorable="d" 
  d:DesignHeight="450" d:DesignWidth="800"
    Title="AddDailyNutritionPlan">
<Grid Background="#A4EE6A" >
    <ComboBox Name="cmbnutritionplan" ItemsSource="{Binding NutritionPlans}" 
              HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="119,36,0,0">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding NutritionPlanName}" />
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
    <ComboBox Name="cmbweekday" ItemsSource="{Binding Path=WeekDays}" HorizontalAlignment="Left" 
              VerticalAlignment="Top" Width="120" Margin="119,72,0,0" RenderTransformOrigin="1.701,0.613">

    </ComboBox>
</Grid>

Rkurel
  • 85
  • 1
  • 7
  • 1
    Possible duplicate of [How to bind an enum to a combobox control in WPF?](https://stackoverflow.com/questions/6145888/how-to-bind-an-enum-to-a-combobox-control-in-wpf) – FoggyFinder Jun 02 '18 at 20:12

2 Answers2

0

I don't have the specifics right now but what I did was something like this.

  enum WeekDay { Mon, Tues };
  Dictionary<string, WeekDay> dic = new Dictionary<string, WeekDay>();
  foreach (var v in WeekDay.Enumerate)  //this is not the correct syntax 
  {
      dic.Add(v.ToString(), v);
  }

Bind the Dictionary;

paparazzo
  • 44,497
  • 23
  • 105
  • 176
0

If you want to be able to simply bind an enum from your XAML you can write a markup extension class. I've written a blog post about it some time ago: http://simonkatanski.blogspot.com/2013/02/enum-combobox-using-markupextension.html

Here's the code:

public class EnumValuesExtension : MarkupExtension
{
    private Type _enumType;
    private String _resourceName;
    private bool _addEmptyValue = false;
    // Enumeration type
    public Type EnumType
    {
        set { _enumType = value; }
    }
    // Name of the class of the .resx file        
    public String ResourceName
    {
        set { _resourceName = value; }
    }
    // Add empty value flag        
    public Boolean AddEmptyValue
    {
        set { _addEmptyValue = value; }
    }
    public EnumValuesExtension()
    {
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        // Enumeration type not passed through XAML
        if (_enumType == null)
            throw new ArgumentNullException("EnumType (Property not set)");
        if (!_enumType.IsEnum)
            throw new ArgumentNullException("Property EnumType must be an enum");
        // Bindable properties list
        List<dynamic> list = new List<dynamic>();

        if (!String.IsNullOrEmpty(_resourceName))
        {
            // Name of the resource class
            Type type = Type.GetType(_resourceName);
            if (type == null)
                throw new ArgumentException(
                    "Resource name should be a fully qualified name");
            // We iterate through the Enum values
            foreach (var enumName in Enum.GetNames(_enumType))
            {
                string translation = string.Empty;
                var property = type.GetProperty(enumName,
                    BindingFlags.Static |
                    BindingFlags.Public |
                    BindingFlags.NonPublic);
                // If there's not translation for specific Enum value,
                // there'll be a message shown instead
                if (property == null)
                    translation = String.Format(
                        "Field {0} not found in the resource file {1}",
                        enumName,
                        _resourceName);
                else
                    translation = property.GetValue(null, null).ToString();

                list.Add(GetNamed(translation, enumName));
            }
            // Adding empty row
            if (_addEmptyValue)
                list.Add(GetEmpty());
            return list;
        }
        // If there's no resource provided Enum values will be used
        // without translation
        foreach (var enumName in Enum.GetNames(_enumType))
            list.Add(GetNamed(enumName, enumName));

        if (_addEmptyValue)
            list.Add(GetEmpty());

        return list;
    }

    // Create one item which will fill our ComboBox ItemSource list
    private dynamic GetNamed(string translation, string enumName)
    {
        // We create a bindable context
        dynamic bindableResult = new ExpandoObject();
        // This dynamically created property will be
        // bindable from XAML (through DisplayMemberPath or wherever)
        bindableResult.Translation = translation;
        // We're setting the value, which will be passed to SelectedItem
        // of the ComboBox
        bindableResult.Enum = enumName;
        return bindableResult;
    }

    // Create one empty item which will fill our ComboBox ItemSource list
    private dynamic GetEmpty()
    {
        dynamic bindableResult = new ExpandoObject();
        bindableResult.Translation = String.Empty;
        bindableResult.Enum = null;
        return bindableResult;
    }
}

You can use this class in your code like this:

<StackPanel>
<ComboBox Height="100" Width="200"
          SelectedValuePath="Enum" 
          DisplayMemberPath="Translation"
          ItemsSource="{Binding Source={local:EnumValues EnumType=local:TestEnum}}"
          Margin="98,0,76,0"
          SelectedValue="{Binding SelectedItemInYourViewModel}"/>
</StackPanel>

All you do then is pass your Enum as the Enum type in the above xaml. This way you can have a generic way of using enums from xaml.

The version I've pasted here and the one in the blog has extra code for hot-switching values in combo with their translated equivalents (if you are working on multi-language application) - you should be able to easily remove that code.

Simon Katanski
  • 426
  • 5
  • 8