Search code examples
c#wpfxamlwcf-binding

Can I Forward IsMouseOver event to a sibling in XAML


I would like to forward the IsMouseOver event from one XAML element to one of it's siblings.
I might be able to do this through code-behind using a RaiseEvent(...) call but I would rather not.
Is it possible to bind the IsMouseOver events from one sibling to another?

For example:
In the code below, the IsMouseOver event for the BlueBorder element turns the border from Blue to Green.
I would like the BlueBorder to turn green when the mouse is over the RedBorder element as well
(obviously, I could put an IsMouseOver trigger in the RedBorderStyle but that would not do for my real-world purpose)

<Window.Resources>
    <Style x:Key="BlueBorderStyle" TargetType="{x:Type Border}">
        <Setter Property="Background" Value="Blue"/>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="Green"/>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="False">
                <Setter Property="Background" Value="Blue"/>
            </Trigger>
        </Style.Triggers>
    </Style>

    <Style x:Key="RedBorderStyle" TargetType="{x:Type Border}">
        <Setter Property="Background" Value="Red"/>
    </Style>
</Window.Resources>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="1*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Border x:Name="BlueBorder" Grid.Column="0" Style="{StaticResource BlueBorderStyle}"/>
    <Border x:Name="RedBorder" Grid.Row="1" Style="{StaticResource RedBorderStyle}"/>
</Grid>

(Or maybe I'm just approaching this in the wrong way?)

For a bit of background:
I have a UserControl with a header above and a ScrollView below. The ScrollView is written such that when the mouse is over the ScrollView the ScrollBars are visible and when the mouse leaves, the scrollbars fade away. Unfortunately, the scrollbars also fade away when the mouse goes to the header which is not what I want.
I could span the ScrollView to include the header but then the ScrollView's viewport also includes the header and this isn't right either.

Suggestions?


Solution

  • You can try triggering on the container's IsMouseOver (that is common to both elements). In this example it will be the Grid.

    <Window.Resources>
        <Style x:Key="BlueBorderStyle" TargetType="{x:Type Border}">
            <Setter Property="Background" Value="Blue"/>
            <Style.Triggers>
                <DataTrigger  Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Grid}, AncestorLevel=1}}" Value="True">
                    <Setter Property="Background" Value="Green"/>
                </DataTrigger>
                <DataTrigger  Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Grid}, AncestorLevel=1}}" Value="False">
                    <Setter Property="Background" Value="Blue"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    
        <Style x:Key="RedBorderStyle" TargetType="{x:Type Border}">
            <Style.Triggers>
                <DataTrigger  Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Grid}, AncestorLevel=1}}" Value="True">
                    <Setter Property="Background" Value="Purple"/>
                </DataTrigger>
                <DataTrigger  Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Grid}, AncestorLevel=1}}" Value="False">
                    <Setter Property="Background" Value="Red"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Border x:Name="BlueBorder" Grid.Column="0" Style="{StaticResource BlueBorderStyle}"/>
        <Border x:Name="RedBorder" Grid.Row="1" Style="{StaticResource RedBorderStyle}"/>
    </Grid>