如何为WPF中Height=Auto的Grid的RowDefinition高度变化添加动画
实现思路
直接对RowDefinition的Height属性做动画需要处理动态高度的问题,我们可以把第一行的所有控件包裹在一个独立容器内,通过读取容器的实际渲染高度作为动画的目标值,适配任意动态内容的场景。
修改后的XAML代码
<Grid> <Grid.RowDefinitions> <!-- 给第一行的RowDefinition加名称方便后续操作 --> <RowDefinition Height="Auto" x:Name="FirstRow"/> <RowDefinition Height="50"/> </Grid.RowDefinitions> <!-- 第一行所有控件包裹在StackPanel/Grid容器中,用于获取实际高度 --> <StackPanel x:Name="FirstRowContainer" Grid.Row="0"> <!-- 原第一行的所有控件放在该容器内 --> <TextBlock Text="动态测试内容1" FontSize="24" Margin="0 10 0 5"/> <TextBlock Text="动态测试内容2" FontSize="16" Margin="0 0 0 15"/> </StackPanel> <ToggleButton x:Name="tb" Grid.Row="1" Content="收起" Click="tb_Click"/> </Grid>
后台逻辑代码
private void tb_Click(object sender, RoutedEventArgs e) { bool isCollapse = tb.IsChecked == true; // 可自行调整动画时长 Duration animDuration = new Duration(TimeSpan.FromMilliseconds(300)); DoubleAnimation heightAnim = new DoubleAnimation { Duration = animDuration, // 可选添加缓动函数让动画更自然 EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseInOut } }; if (isCollapse) { // 收起逻辑:先把行高从Auto固定为当前实际高度,避免出现跳变 FirstRow.Height = new GridLength(FirstRowContainer.ActualHeight); heightAnim.From = FirstRowContainer.ActualHeight; heightAnim.To = 0; tb.Content = "展开"; } else { // 展开逻辑:以容器实际高度为动画目标值 heightAnim.From = 0; heightAnim.To = FirstRowContainer.ActualHeight; // 动画完成后将行高改回Auto,后续第一行内容变化时可自动适配高度 heightAnim.Completed += (s, args) => { FirstRow.Height = GridLength.Auto; }; tb.Content = "收起"; } // 清除原有动画后触发新动画 FirstRow.BeginAnimation(RowDefinition.HeightProperty, null); FirstRow.BeginAnimation(RowDefinition.HeightProperty, heightAnim); }
注意事项
- 如果触发动画前第一行的内容有更新,可先调用
FirstRowContainer.UpdateLayout()确保读取到的ActualHeight是最新的实际高度 - 该方案完全依赖容器的实际渲染高度,不需要提前预设行高,适配所有动态内容的场景
内容的提问来源于stack exchange,提问作者Loraler
相关产品推荐
相关产品推荐

