0

I have a form with two ComboBoxes. The second ComboBox holds a list of customers. The first ComboBox lets the user choose how they want to search for Customers and see them displayed. Currently, someone has it running different stored procedures for each search type just to change the way it's displayed in the drop down. I would like to change it so that it chooses a DataTemplate based on the selection of the first drop down.

E.G. If you choose First/Last from the first ComboBox, the customers will display in the second ComboBox drop down as:

John Doe
1234 Fake St. Chandler, Az
(480) 555-2342

If you change it to Last/First, the customers will then show in the drop down as:

Doe, John
1234 Fake St. Chandler, Az
(480) 555-2342

Or if you choose Email, it would display as:

JDoe@gmail.com
John Doe
1234 Fake St. Chandler, Az

I know how to write the templates, but how do I set the second ComboBox.ItemTemplate based on the selection of the first ComboBox? I'd be fine with using Triggers or C# code.

EDIT: Here is one attempt I just tried, but the template doesn't change. I know the trigger is working because the background turns green.

<UserControl.Resources>
    <DataTemplate x:Key="ComboBoxCustomTemplate">
        <Grid Margin="3 3">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="{Binding Name}" />
            <WrapPanel Grid.Row="1" Orientation="Horizontal">
                <TextBlock Text="Address:" />
                <TextBlock HorizontalAlignment="Left" Foreground="#003366" Margin="3,0,0,0" Text="{Binding Address}" />
            </WrapPanel>
            <WrapPanel Grid.Row="2" Orientation="Horizontal">
                <TextBlock Text="Phone:" />
            <TextBlock HorizontalAlignment="Left" Foreground="#003366" Margin="3,0,0,0" Text="{Binding Telephone}" />
            </WrapPanel>                                
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="ComboBoxEmailTemplate">
        <Grid Margin="3 3">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="{Binding Email}" />
            <WrapPanel Grid.Row="1" Orientation="Horizontal">
                <TextBlock Text="Address:" />
                <TextBlock HorizontalAlignment="Left" Foreground="#003366" Margin="3,0,0,0" Text="{Binding Address}" />
            </WrapPanel>
            <WrapPanel Grid.Row="2" Orientation="Horizontal">
                <TextBlock Text="Phone:" />
                <TextBlock HorizontalAlignment="Left" Foreground="#003366" Margin="3,0,0,0" Text="{Binding Telephone}" />
            </WrapPanel>
        </Grid>
    </DataTemplate>
</UserControl.Resources>

<ComboBox Name="cbSearchFilter" Padding="5,1" Width="150" Margin="3,3,10,3" SelectionChanged="cbSearchFilter_SelectionChanged" Style="{StaticResource VirtualizingComboBox}">
            <ComboBoxItem Content="Parent Last/First" Tag="LastFirst" />
            <ComboBoxItem Content="Parent First/Last" Tag="FirstLast" />
            <ComboBoxItem Content="Student First/Last" Tag="Student" IsSelected="True" />
            <ComboBoxItem Content="Parent Phone Number" Tag="PhoneNumber"/>
            <ComboBoxItem Content="Parent Email" Tag="Email"/>
        </ComboBox>

<ComboBox Name="cbCustomers"
                SelectedValuePath="FamilyID"
                ItemTemplate="{StaticResource ComboBoxCustomTemplate}"
                Grid.Column="1" Grid.Row="2" IsEditable="True" StaysOpenOnEdit="True"
                KeyboardNavigation.IsTabStop="False" SelectionChanged="rcbCustomers_SelectionChanged" KeyUp="rcbCustomers_KeyUp" KeyDown="rcbCustomers_KeyDown" >
            <ComboBox.Style>
                <Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource VirtualizingComboBox}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ElementName=cbSearchFilter, Path=SelectedItem.Tag}" Value="Email">
                            <DataTrigger.Setters>
                                <Setter Property="Background" Value="Green" />
                                <Setter Property="ItemTemplate" Value="{StaticResource ComboBoxEmailTemplate}" />
                            </DataTrigger.Setters>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ComboBox.Style>
        </ComboBox>
xr280xr
  • 12,621
  • 7
  • 81
  • 125
  • Are you familiar with the `DataTemplateSelector` class and MVVM pattern? I've described similar behavior for a single view here: http://stackoverflow.com/questions/5309099/changing-the-view-for-a-viewmodel/5310213#5310213, but the ComboBox class is somehow different. Implement correct data templates and a view model and after that post the code, then it will be easier to me to answer. – vortexwolf Nov 04 '11 at 19:30
  • 1
    Thanks vorrtex.I was looking at the DataTemplateSelector, but my impression was that's for choosing a template on an item by item basis; where the condition is based on a property or properties of the item being bound. Where I want to use the same template for all items where the condition is the other ComboBox's selected value. I'm not familiar with MVVP pattern so I'm not sure I'm following you there. The customers ComboBox is just currently being bound to a DataView. But regardless of what I already have, I'm really just looking to set the ItemTemplate based on the value of another control. – xr280xr Nov 04 '11 at 19:46
  • Ok, the implementation of a correct view model takes much time, so I'll not insist on rewriting the code. In your current xaml code the `DataTrigger` can't overwrite the existing property. Try to use the `DataTrigger.EnterActions` and the `ObjectAnimationUsingKeyFrame` for setting the `ItemTemplate`. – vortexwolf Nov 04 '11 at 20:04

2 Answers2

0

You can use ItemTemplateSelector. It will choose the right template for you based on selection in first ComboBox.

icebat
  • 4,696
  • 4
  • 22
  • 36
  • I was looking at that, but how do you access the value of the first ComboBox in the ItemTemplateSelector? – xr280xr Nov 04 '11 at 19:51
  • @xr280xr If you used the MVVM pattern, you could observe combobox changes in the parent view model and update all items in the child collection. Like `this.Customers.ForEach(c => c.ViewType == View.FirstLast)` – vortexwolf Nov 04 '11 at 20:07
0

You can use a DataTrigger like this:

<Style x:Key="ComboBox2Style">
    <Setter Property="ItemTemplate" Value="{StaticResource DefaultTemplate}" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding SelectedValue, ElementName=ComboBox1}" Value="LastFirst">
            <Setter Property="ItemTemplate" Value="{StaticResource LastNameFirstTemplate}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding SelectedValue, ElementName=ComboBox1}" Value="Email">
            <Setter Property="ItemTemplate" Value="{StaticResource EmailTemplate}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

Edit

Just noticed the edit to your question. The problem with what you have is the ItemTemplate is defined in the <ComboBox /> tag. According to WPF's Dependency Property Precedence rules, a value defined directly in the tag overwrites any Styled or Triggered values. To make the Trigged template take effect, set the default ItemTemplate in your ComboBox's Style

Rachel
  • 130,264
  • 66
  • 304
  • 490