0
votes

I have a ListBox with an ItemTemplateSelector. All the data templates returned by the template selector have a Border. I'd like to change the border's background color when the mouse is over it. To achieve this, I added to the listbox a ListBoxItem control template with a trigger for IsMouseOver but I have no idea how to reference the data template's Border from the trigger's setter. My best bet was the following setter but it had no effect:

<Trigger Property="IsMouseOver" Value="True">
    <Setter Property="Border.Background" Value="Yellow" />
</Trigger>

Is there a way to do this in XAML, or perhaps to drill down the visual tree in code to find the Border somehow?

I'd also like to change the Border's background color when the item is selected in the ListBox. I know that I could change Foreground with a ListBoxItem style like the following:

            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Foreground" Value="Red"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>

but unlike Foreground, Background is not inherited, so the Border in the DataTemplate will not receive the trigger's brush.

1
The item templates should trigger on what happens outside, not the other way around, because there is no way to know what is inside. Also, stay away from messing with visual trees, nothing good ever comes of that.H.B.
@H.B. True, I can place the IsMouseOver trigger in the data template, so that is solved. But the data template will never know that it resides in a ListBoxItem and it has become the selected item, so it should change color. Or will it? Only the ListBox knows that, which is why I use a ListBoxItem control template.Drew
Well, if selection is independent from the DataTemplate the question is whether it should affect anything within the template in the first place. It's not something one would commonly do. If the DataTemplate should respond to selection it might make sense to also put that logic inside that DataTemplate in the first place.H.B.
@H.B. I want to indicate which item is selected by changing the background of the Border (returned by the DataTemplate) of the selected item instead of the default background color change painted by ListBoxItem. I realized the control template cannot access the visual tree of the Content. Instead, I could use a style (see updated post) if the Background property was inherited. As it is not inherited, I still haven't found a solution.Drew

1 Answers

1
votes

I was able to change the Background of the Border when the item is selected in a ListBox using a data trigger in the data template.

        <DataTemplate DataType="{x:Type model:Topic}" x:Key="TopicNameDataTemplate">
            <Grid>
                <Border x:Name="Border" ... >
                    ...
                </Border>
            </Grid>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"
                             Value="True">
                    <Setter TargetName="Border" Property="Background" Value="Orange"/>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>