tags:

views:

17609

answers:

7

As an example take the following code:

public enum ExampleEnum { FooBar, BarFoo }

public class ExampleClass : INotifyPropertyChanged
{
    private ExampleEnum example;

    public ExampleEnum ExampleProperty 
    { get { return example; } { /* set and notify */; } }
}

I want a to databind the property ExampleProperty to a ComboBox, so that it shows the options "FooBar" and "BarFoo" and works in mode TwoWay. Optimally I want my ComboBox definition to look something like this:

<ComboBox ItemsSource="What goes here?" SelectedItem="{Binding Path=ExampleProperty}" />

Currently I have handlers for the ComboBox.SelectionChanged and ExampleClass.PropertyChanged events installed in my Window where I do the binding manually.

Is there a better or some kind of canonical way? Would you usually use Converters and how would you populate the ComboBox with the right values? I don't even want to get started with i18n right now.

Edit

So one question was answered: How do I populate the ComboBox with the right values.

Retrieve Enum values as a list of strings via an ObjectDataProvider from the static Enum.GetValues method:

<Window.Resources>
    <ObjectDataProvider MethodName="GetValues"
        ObjectType="{x:Type sys:Enum}"
        x:Key="ExampleEnumValues">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="ExampleEnum" />
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

This I can use as an ItemsSource for my ComboBox:

<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}"/>
+6  A: 

I don't know if it is possible in XAML-only but try the following:

Give your ComboBox a name so you can access it in the codebehind: "typesComboBox1"

Now try the following

typesComboBox1.ItemsSource = Enum.GetValues(typeof(ExampleEnum));
rudigrobler
+5  A: 

oooops, I stand corrected...

it is possible to do it XAML only, check out this post: http://blogs.msdn.com/wpfsdk/archive/2007/02/22/displaying-enum-values-using-data-binding.aspx

rudigrobler
Thanks for the link, this clears up where I can get the available values for my ComboBox. Sadly I can't use this to bind it to a Property of an object. The link only shows how to use the chosen value as text basically.
Maximilian
A: 

Try using

<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}"
    SelectedValue="{Binding Path=ExampleProperty}" />
rudigrobler
This doesn't work. The combobox will just show an empty text and changing it won't do anything.I guess throwing in a converter here would be the best solution.
Maximilian
Why the downvote?? Geez..
Meleak
+1  A: 

I tried the SelectedValue and it works...

Here is my example code and here is a blog post about it!

rudigrobler
Uh. Thanks for spelling it out for me like that! I was overcomplicating things before even trying the easy way ;-)
Maximilian
+3  A: 

you can consider something like that:

  1. define a style for textblock, or any other control you want to use to display your enum:

        <Style x:Key="enumStyle" TargetType="{x:Type TextBlock}">
            <Setter Property="Text" Value="&lt;NULL&gt;"/>
            <Style.Triggers>
                <Trigger Property="Tag">
                    <Trigger.Value>
                        <proj:YourEnum>Value1<proj:YourEnum>
                    </Trigger.Value>
                    <Setter Property="Text" Value="{DynamicResource yourFriendlyValue1}"/>
                </Trigger>
                <!-- add more triggers here to reflect your enum -->
            </Style.Triggers>
        </Style>
    
  2. define your style for ComboBoxItem

        <Style TargetType="{x:Type ComboBoxItem}">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <TextBlock Tag="{Binding}" Style="{StaticResource enumStyle}"/>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
  3. add a combobox and load it with your enum values:

            <ComboBox SelectedValue="{Binding Path=your property goes here}" SelectedValuePath="Content">
                <ComboBox.Items>
                    <ComboBoxItem>
                        <proj:YourEnum>Value1</proj:YourEnum>
                    </ComboBoxItem>
                </ComboBox.Items>
            </ComboBox>
    

if your enum is large, you can of course do the same in code, sparing a lot of typing. i like that approach, since it makes localization easy - you define all the templates once, and then, you only update your string resource files.

Greg
the SelectedValuePath="Content" helped me here. I have my ComboBoxItems as string values, and kept getting can't convert ComboBoxItem to my Enum Type. Thanks
adriaanp
+13  A: 

I explored this and have a solution that you can use (complete with localization) in WPF located here.

ageektrapped
This is a very nice solution and is more "the answer" than the other provided - although that one does also work. Especially love the use of the DisplayStringAttribute and being able to flow that back and forth. Very very nice.
Paul Prewett
Looks like the site is down.
Recep
Thanks for pointing that out. It's back up.
ageektrapped
Awesome post. Thanks for the link.
Benny Jobigan
A: 

Using the ObjectDataProvider (or a collectionviewsource wrapping one for ordering) works well for me, except that if I load an item the SelectedValue reverts to the first item in the enum, instead of the actual value; I want it to use the itemssource and use the data from the item.

Any ideas? IsSynchronizedWithCurrentItems=true, didn't have the desired effect.

blackSphere