Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically changing ItemsSource of a WPF ComboBox

I have a WPF application that contains two comboboxes (we'll call them cbox1 and cbox2). cbox1 has its ItemsSource bound to an enum via XAML like this:

<Window.Resources>
    <local:EnumDescriptionConverter x:Key="enumDescriptionConverter"/>
    <ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="cbox1DataProvider">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="local:MyModel+ModeOfTransportationEnum"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

<ComboBox x:Name="cbox1" ItemsSource="{Binding Source={StaticResource cbox1DataProvider}}" SelectionChanged="cbox1_SelectionChanged">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Converter={StaticResource enumDescriptionConverter}}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

The enum that cbox1's ItemsSource is bound to looks like this:

public enum ModeOfTransportationEnum
{
    [Description("BMW X5")]
    BmwX5,
    [Description("Toyota Camry")]
    ToyotaCamry,
    [Description("Ford Focus")]
    FordFocus
}

When my user selects an item in cbox1, I want to dynamically define the ItemsSource for cbox2. For example, if my user selects "Toyota Camry" from cbox1, I want cbox2 to display the values "Red" and "Black". If the user chooses "Ford Focus" from cbox1, I might want cbox2 to display "Silver", "Red" and "Blue".

I've probably over-simplified the example but in a nutshell, I have three enums that I want to use for the .ItemsSource binding of cbox2. I want to set the appropriate enum as the .ItemsSource for cbox2 based on what the user has selected in cbox1. I was thinking that this could be accomplished with something similar to:

cbox2.SetBinding(ComboBox.ItemsSourceProperty, new Binding("AppropriateEnumGoesHere"));

Unfortunately, this doesn't seem to be working. I don't get an error or anything but I also don't see my enum values being displayed in cbox2. Also, as you can see in my XAML for cbox1 above, I'm using a converter to display the description attribute of each enum value. The enums that I want to use as the .ItemsSource for cbox2 also have description attributes that I want to display instead of the raw enum values and I'm not sure how that should work from code, either. Can anyone point me in the right direction? Thanks!

like image 503
bmt22033 Avatar asked Oct 20 '22 17:10

bmt22033


1 Answers

The easiest way to do this is to create a property to bind to the second ComboBox.ItemsSource property. Now I've done this with classes many times, but not enums, so it might not work, but it should. Normally, my classes would have to derive from one base class, so that the property could be of that type. In your case, you could try this:

public ObservableCollection<Enum> Collection2 { get; set; } // Implement INPC interface

...

<ComboBox x:Name="cbox2" ItemsSource="{Binding Collection2}" ... />

Now lets assume that you have other collections that contain all of the values of your enums:

private List<BmwColours> bmwColours; // Fill these collections with correct values
private List<ToyotaColours> toyotaColours;
private List<FordColours> fordColours;

When the user makes a selection from the first ComboBox, you can fill the Collection2 property with the correct enum values something like this:

Collection2 = new ObservableCollection<Enum>();
if (cbox1.SelectedItem == ModeOfTransportationEnum.BmwX5)
    foreach (Enum enumInstance in bmwColours) Collection2.Add(enumInstance);
else if (cbox1.SelectedItem == ModeOfTransportationEnum.ToyotaCamry)
    foreach (Enum enumInstance in toyotaColours) Collection2.Add(enumInstance);
...

Now Collection2 is full of the correct enum values. You might need to tweak this a bit to suit your needs, but it should do the trick.

like image 68
Sheridan Avatar answered Oct 30 '22 22:10

Sheridan