views:

60

answers:

2

How do I conditionally bind data to a combo box? I have a combo box that by default should display an ID. However, if the user checks a check box then the display should display both the ID and a NAME. For example, "OO1: Sam". I have the default ID displaying correctly. I'm just not sure how to get both the ID and the NAME to display based on the "IsChecked" state of the check box.

WPF and C# .Net 3.5

+3  A: 

Here's one way, using a style on the ComboBox with triggers to set the ItemTemplate dynamically:

Edit: Changing the style into a resource. Note that this is still binding to the CheckBox directly using element binding - if you want it to be more flexible you could bind the CheckBox's IsChecked property to a property of your ViewModel and rely on that changing rather than IsChecked.

Let's move the style into the Resources section of our Window:

<Window.Resources>
    <Style x:Key="myStyle" TargetType="ComboBox">
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="{Binding Name}" />
                    </StackPanel>
                </DataTemplate>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <DataTrigger Binding="{Binding IsChecked,ElementName=chk}" Value="True">
                <Setter Property="ItemTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding ID}" />
                                <TextBlock Text=": " />
                                <TextBlock Text="{Binding Name}" />
                            </StackPanel>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

Now we define the CheckBox and a couple of ComboBoxes that rely on it:

<CheckBox x:Name="chk" Content="Click Me" />

<ComboBox ItemsSource="{Binding}" Style="{StaticResource myStyle}" />

<ComboBox ItemsSource="{Binding}" Style="{StaticResource myStyle}" />
Matt Hamilton
Matt, Thank you very much! That is exactly what I was looking for. Of course i'm sure you can tell I'm new to WPF. I knew it had to be a lot easier than the way I was going about it. Now, is there a way to make it a "StaticResource", not sure if that's the right term. And how would you use it in a combo box definition?
GAR8
Are you planning on reusing the style across multiple ComboBoxes, GAR8? I could edit the answer and change it into a resource if you like - it's not a big change. If you're not reusing it in more than one ComboBox, it's not really worth making it a resource IMHO.
Matt Hamilton
Yes, Matt there are a two combo boxes that will be impacted by this single check box state as well as some data contained in a DataGrid. I will also be using this same concept on another check box that will impact three combo boxes a text box and data in the same DataGrid. So having a resource to minimize and reuse code would be very helpful. Thank you so much for the help on this. G
GAR8
Matt, thank you, that is very cool. I had it working through c# events etc. but I like binding better, less code in the end. Also, I already had a defined Style StaticResource for the combo box so I was able to add "BasedOn" to your example and include the existing resource and then use your new resource in the combo box. This worked out great because the previous resource was only for general combo box stuff, alignment, background, width... Thanks again. G
GAR8
+1  A: 

I would do that in the ViewModel. You could have a viewmodel for your combo box items, another one for whatever screen the checkbox lives on, and some way for the checkbox viewmodel to tell the item viewmodels when its value has changed. The item viewmodel then has conditional logic in its Text property (or whatever you call it), and implements the usual INotifyPropertyChanged pattern to notify the UI when its text has changed.

The benefit: this way you can write unit tests for this behavior. (And if it's worth putting in, it's worth writing unit tests for.)

Joe White