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

WPF ListView项对称动画实现:保留滚动功能的技术咨询

WPF ListView 对称动画与滚动兼容解决方案

要实现ListView项的对称放大动画(鼠标悬停时按钮从中心向外放大),但当前代码设置导致ListView无法滚动且项布局偏移,以下是修复方案:

问题根源

  1. ScrollViewer.CanContentScroll="False"会关闭WPF的虚拟化滚动机制,直接导致ListView失去滚动功能,同时破坏VirtualizingStackPanel的布局计算
  2. 直接修改按钮的Width/Height会改变元素的布局占位,触发周围项重新排列,无法实现对称动画且出现偏移

修复方案

核心思路

  • 恢复ListView的虚拟化滚动功能
  • 使用视觉层缩放(RenderTransform)代替修改布局属性,保证动画对称且不影响其他项布局

修改后的XAML代码

<ListView
    x:Name="ListView1"
    HorizontalAlignment="Stretch"
    VerticalAlignment="Center"
    ScrollViewer.HorizontalScrollBarVisibility="Auto">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel
                CacheLength="10,10"
                CacheLengthUnit="Pixel"
                IsItemsHost="True"
                IsVirtualizing="True"
                Orientation="Horizontal"
                ScrollUnit="Pixel"
                VirtualizationMode="Recycling">
            </VirtualizingStackPanel>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <ListViewItem>
        <Button
            Width="100"
            Height="120"
            Margin="3"
            HorizontalAlignment="Center"
            FontSize="18"
            FontWeight="Bold"
            Foreground="MediumPurple"
            MouseEnter="Button_MouseEnter"
            MouseLeave="Button_MouseLeave">
            <!-- 设置中心缩放原点 -->
            <Button.RenderTransformOrigin>
                <Point>0.5,0.5</Point>
            </Button.RenderTransformOrigin>
            <Button.RenderTransform>
                <ScaleTransform x:Name="BtnScale" ScaleX="1" ScaleY="1"/>
            </Button.RenderTransform>
        </Button>
    </ListViewItem>
    <!-- 更多ListViewItem项 -->
</ListView>

修改后的C#代码

private void Button_MouseEnter(object sender, MouseEventArgs e)
{
    if (sender is not Button button) return;
    if (button.RenderTransform is not ScaleTransform scale) return;

    // 按比例缩放,对应原100→130(1.3倍)、120→150(1.25倍)的效果
    var scaleXAnim = new DoubleAnimation(1.3, TimeSpan.FromSeconds(0.3));
    var scaleYAnim = new DoubleAnimation(1.25, TimeSpan.FromSeconds(0.3));

    scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleXAnim);
    scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleYAnim);
}

private void Button_MouseLeave(object sender, MouseEventArgs e)
{
    if (sender is not Button button) return;
    if (button.RenderTransform is not ScaleTransform scale) return;

    var scaleXAnim = new DoubleAnimation(1, TimeSpan.FromSeconds(0.3));
    var scaleYAnim = new DoubleAnimation(1, TimeSpan.FromSeconds(0.3));

    scale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleXAnim);
    scale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleYAnim);
}

更优雅的无代码实现(推荐)

用Style Trigger替代后台事件,完全在XAML中实现动画,更符合WPF的MVVM思想:

<Window.Resources>
    <Style TargetType="Button" x:Key="AnimatedListItemBtn">
        <Setter Property="Width" Value="100"/>
        <Setter Property="Height" Value="120"/>
        <Setter Property="Margin" Value="3"/>
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="FontSize" Value="18"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Foreground" Value="MediumPurple"/>
        <!-- 中心缩放原点 -->
        <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <ScaleTransform ScaleX="1" ScaleY="1"/>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Trigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation 
                                Storyboard.TargetProperty="RenderTransform.ScaleX" 
                                To="1.3" 
                                Duration="0:0:0.3"/>
                            <DoubleAnimation 
                                Storyboard.TargetProperty="RenderTransform.ScaleY" 
                                To="1.25" 
                                Duration="0:0:0.3"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation 
                                Storyboard.TargetProperty="RenderTransform.ScaleX" 
                                To="1" 
                                Duration="0:0:0.3"/>
                            <DoubleAnimation 
                                Storyboard.TargetProperty="RenderTransform.ScaleY" 
                                To="1" 
                                Duration="0:0:0.3"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.ExitActions>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<ListView
    x:Name="ListView1"
    HorizontalAlignment="Stretch"
    VerticalAlignment="Center"
    ScrollViewer.HorizontalScrollBarVisibility="Auto">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel
                CacheLength="10,10"
                CacheLengthUnit="Pixel"
                IsItemsHost="True"
                IsVirtualizing="True"
                Orientation="Horizontal"
                ScrollUnit="Pixel"
                VirtualizationMode="Recycling">
            </VirtualizingStackPanel>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <ListViewItem>
        <Button Style="{StaticResource AnimatedListItemBtn}"/>
    </ListViewItem>
    <!-- 更多项 -->
</ListView>

关键修改说明

  1. 恢复滚动功能:移除ScrollViewer.CanContentScroll="False",让ListView使用虚拟化滚动,同时保留VirtualizingStackPanel的性能优势
  2. 修正布局偏移:移除VirtualizingStackPanel.HorizontalAlignment="Center",让面板填满ListView水平空间,确保滚动区域计算正确
  3. 对称动画实现:通过RenderTransformOrigin="0.5,0.5"设置缩放原点为元素中心,使用ScaleTransform在视觉层缩放,不会改变元素的布局占位,避免周围项偏移

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 15:24:52