Randall Deetz
Randall Deetz

Reputation: 524

XAML ControlTemplate Trigger Fails for DataTemplate

I'd like to display different combobox images based on IsDropDownOpen. Not sure how to access 'imgArrow' properly.

<Style TargetType="ComboBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ComboBox" >
                <Grid Background="{DynamicResource ComboDropdownNormal}" Height="50" Width="326" >
                    <ContentPresenter Content="{TemplateBinding SelectionBoxItem}" >
                        <ContentPresenter.ContentTemplate>
                            <DataTemplate>
                                <Grid>
                                    <TextBlock Text="{Binding}" />

                                    <Image x:Name="imgArrow"
                                           Source="{DynamicResource ComboBoxArrowNormalImage}"
                                           RenderOptions.BitmapScalingMode="HighQuality" />
                                </Grid>
                            </DataTemplate>

                        </ContentPresenter.ContentTemplate>
                    </ContentPresenter>

                    <ToggleButton ClickMode="Press" Focusable="false"
                                  IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                                  Template="{StaticResource ComboBoxToggleButtonTmp}" />

                    <Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" >
                        <ContentControl>
                            <Border x:Name="DropDownBorder" 
                                    Background="{DynamicResource ComboDropdownNormal}"
                                    MaxHeight="540" MinWidth="{TemplateBinding ActualWidth}" >
                            </Border>
                        </ContentControl>
                    </Popup>

                </Grid>

                <ControlTemplate.Triggers>

                    <Trigger Property="HasItems" Value="false">
                        <Setter TargetName="DropDownBorder" Property="MinHeight" Value="95" />
                    </Trigger>
<!-- FAILS -->
                    <Trigger Property="IsDropDownOpen" Value="True">
                        <Setter TargetName="imgArrow" Property="Image.Source" Value="{DynamicResource ComboBoxArrowHoverImage}" />
                    </Trigger>
                    <Trigger Property="IsDropDownOpen" Value="False">
                        <Setter TargetName="imgArrow" Property="Image.Source" Value="{DynamicResource ComboBoxArrowNormalImage}" />
                    </Trigger>
<!-- FAILS -->
                </ControlTemplate.Triggers>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The bold triggers in the code above fail. Any assistance would be greatly appreciated. Thanks!

Upvotes: 0

Views: 374

Answers (2)

rmojab63
rmojab63

Reputation: 3631

In your scenario, you should use a DataTrigger

<DataTemplate>
    <Grid>
        <TextBlock Text="{Binding}" />
        <Image x:Name="imgArrow"
               Source="{DynamicResource ComboBoxArrowNormalImage}"
               RenderOptions.BitmapScalingMode="HighQuality" />
    </Grid>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}, Path=IsDropDownOpen}"
                     Value="True">
            <Setter TargetName="imgArrow"
                    Property="Source"
                    Value="{DynamicResource ComboBoxArrowHoverImage}" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

However, I cannot get why you have put the image in a DataTemplate in the ContentPresenter. I'm not sure this is the right way of styling.

If you want to change the source of an Image, while IsDropDownOpen is True, one way is to put everything is a Grid:

<Grid >
    <ContentPresenter />
    <Image />
    <ToggleButton />
    <Popup/>
</Grid>

and set the BackGrounds and Triggers Propertly.

Upvotes: 0

mm8
mm8

Reputation: 169390

A ControlTemplate trigger won't be able to find the Image element in the ContentTemplate of the ContentPresenter but you could apply a Style to the Image element itself directly and remove the IsDropDownOpen triggers from the ControlTemplate:

<ContentPresenter Content="{TemplateBinding SelectionBoxItem}" >
    <ContentPresenter.ContentTemplate>
        <DataTemplate>
            <Grid>
                <TextBlock Text="{Binding}" />
                <Image x:Name="imgArrow" RenderOptions.BitmapScalingMode="HighQuality">
                    <Image.Style>
                        <Style TargetType="Image">
                            <Setter Property="Source" Value="{DynamicResource ComboBoxArrowNormalImage}" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsDropDownOpen, RelativeSource={RelativeSource AncestorType=ComboBox}}" Value="True">
                                    <Setter Property="Source" Value="{DynamicResource ComboBoxArrowHoverImage}" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Image.Style>
                </Image>
            </Grid>
        </DataTemplate>
    </ContentPresenter.ContentTemplate>
</ContentPresenter>

Upvotes: 1

Related Questions