You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

纯XAML实现Border悬停时切换Image源的技术问询

问题描述

我有一个包含Border的UserControl,Border内的StackPanel里有Image和TextBlock元素。想在纯XAML中实现当Border被鼠标悬停时切换Image的Source。目前能轻松修改Border的背景,也能在Image自身悬停时切换源,但希望触发条件是Border的悬停状态。

现有样式代码:

<Style TargetType="TextBlock"  x:Key="Button.Text">
    <Setter Property="FontFamily" Value="{StaticResource Fonts.InterMedium}"/>
    <Setter Property="FontSize" Value="10"/>
    <Setter Property="Foreground" Value="Gray"/>
</Style>

<Style TargetType="Border" x:Key="Button.Border">
    <Setter Property="Background" Value="Gray" />
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Blue" />
        </Trigger>
    </Style.Triggers>
</Style>

现有Border代码:

<Border CornerRadius="6" 
        Width="80"
        HorizontalAlignment="Left"
        Style="{StaticResource Button.Border}"
        >
    <StackPanel>
        <behavior:Interaction.Triggers>
            <behavior:EventTrigger EventName="MouseLeftButtonDown">
                <behavior:InvokeCommandAction Command="{Binding DataContext.RestoreCommand, RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}}" 
                                                />
            </behavior:EventTrigger>
        </behavior:Interaction.Triggers>
        <Image Margin="0, 8, 0, 0"
               HorizontalAlignment="Center"
               Width="24" Height="24"
               >
            <Image.Style>
                <Style TargetType="Image">
                    <Setter Property="Source" Value="component/Resources/Icon.ReverseLeft.png"/>
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Source" Value="component/Resources/Icon.ReverseLeft.Hover.png"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Image.Style>
        </Image>
        <TextBlock Style="{StaticResource Button.Text}"
                   Margin="0, 2, 0, 4"
                   HorizontalAlignment="Center"
                   Text="{DynamicResource Restore}"
                   />
    </StackPanel>
</Border>
解决方案

方法一:在Image的Style中绑定Border的悬停状态

修改Image的Style,将原有的Trigger替换为DataTrigger,通过RelativeSource获取父级Border的IsMouseOver属性作为触发条件:

<Image Margin="0, 8, 0, 0"
       HorizontalAlignment="Center"
       Width="24" Height="24">
    <Image.Style>
        <Style TargetType="Image">
            <Setter Property="Source" Value="component/Resources/Icon.ReverseLeft.png"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=Border}}" Value="True">
                    <Setter Property="Source" Value="component/Resources/Icon.ReverseLeft.Hover.png"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>

方法二:将状态逻辑整合到Border的Style中

如果希望把相关状态统一管理在Border的Style里,可给Image命名后,在Border的Trigger中直接修改其Source:

1. 给Image添加命名

<Image x:Name="ControlIcon"
       Margin="0, 8, 0, 0"
       HorizontalAlignment="Center"
       Width="24" Height="24"
       Source="component/Resources/Icon.ReverseLeft.png"/>

2. 修改Border的Style

<Style TargetType="Border" x:Key="Button.Border">
    <Setter Property="Background" Value="Gray" />
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Blue" />
            <Setter TargetName="ControlIcon" Property="Source" Value="component/Resources/Icon.ReverseLeft.Hover.png"/>
        </Trigger>
        <Trigger Property="IsMouseOver" Value="False">
            <Setter TargetName="ControlIcon" Property="Source" Value="component/Resources/Icon.ReverseLeft.png"/>
        </Trigger>
    </Style.Triggers>
</Style>

注意:这种方式要求Image是Border的直接/间接子元素,且Border与Image处于同一命名空间下。若Border的Style是全局资源,建议重构Border的Template,将Image包含在内以确保TargetName能正确识别。

方法三:使用VisualStateManager(适合多状态管理)

如果需要同时管理多种状态(如按下、禁用等),可使用VisualStateManager实现:

<Border CornerRadius="6" 
        Width="80"
        HorizontalAlignment="Left"
        Style="{StaticResource Button.Border}">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">
            <VisualState x:Name="Normal"/>
            <VisualState x:Name="MouseOver">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ControlIcon" Storyboard.TargetProperty="Source">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="component/Resources/Icon.ReverseLeft.Hover.png"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ColorAnimation Storyboard.TargetProperty="Background.Color" To="Blue" Duration="0"/>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <StackPanel>
        <behavior:Interaction.Triggers>
            <behavior:EventTrigger EventName="MouseLeftButtonDown">
                <behavior:InvokeCommandAction Command="{Binding DataContext.RestoreCommand, RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}}"/>
            </behavior:EventTrigger>
        </behavior:Interaction.Triggers>
        <Image x:Name="ControlIcon"
               Margin="0, 8, 0, 0"
               HorizontalAlignment="Center"
               Width="24" Height="24"
               Source="component/Resources/Icon.ReverseLeft.png"/>
        <TextBlock Style="{StaticResource Button.Text}"
                   Margin="0, 2, 0, 4"
                   HorizontalAlignment="Center"
                   Text="{DynamicResource Restore}"/>
    </StackPanel>
</Border>

内容的提问来源于stack exchange,提问作者zzDiego

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 07:38:14