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

WPF UserControl如何基于内部TextBlock内容实现阶梯式动态高度

问题原因

你当前的实现直接将ScrollViewer放在Grid中,而ScrollViewer默认布局逻辑会占用父容器分配的所有可用高度,因此会直接将UserControl撑到你设置的MaxHeight=64,无法根据内部文本高度动态收缩。

解决方案

需要结合XAML调整和少量后台代码实现阶梯高度适配,修改如下:

1. XAML代码调整

<UserControl x:Class="Test.UI.View.Controls.ErrorBannerControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Test.UI.View.Controls"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="400"
         MinHeight="40" MaxHeight="64"
         Background="#FFF8F8"
         SizeChanged="ErrorBannerControl_SizeChanged"
         Loaded="ErrorBannerControl_Loaded">
    <Grid Margin="16,8,16,8">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="16"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="0" FontFamily="Segoe MDL2 Assets" Text="&#xE783;" 
               FontSize="16" Foreground="Red" 
               VerticalAlignment="Center" />
        
        <ScrollViewer x:Name="ErrorScrollViewer" Grid.Column="1" VerticalScrollBarVisibility="Auto">
            <TextBlock x:Name="TextBlockError" Margin="8,0,0,0" Foreground="Red" FontSize="12"
                   VerticalAlignment="Center" TextWrapping="Wrap" />
        </ScrollViewer>
    </Grid>
</UserControl>

主要改动点:

  • 给UserControl添加SizeChanged和Loaded事件监听,用于宽度变化、初始化时重新计算高度
  • 给ScrollViewer添加x:Name方便后台控制滚动条显隐

2. 后台代码调整

using System;
using System.Windows;
using System.Windows.Controls;

namespace Test.UI.View.Controls
{
    public partial class ErrorBannerControl : UserControl
    {
        public static readonly DependencyProperty ErrorTextProperty =
            DependencyProperty.Register("ErrorText", typeof(string), typeof(ErrorBannerControl),
                new FrameworkPropertyMetadata(ErrorTextChangedCallback));

        public ErrorBannerControl()
        {
            InitializeComponent();
        }

        // 修正依赖属性CLR包装,符合WPF规范
        public string ErrorText
        {
            get => (string)GetValue(ErrorTextProperty);
            set => SetValue(ErrorTextProperty, value);
        }

        private static void ErrorTextChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var errorBannerControl = (ErrorBannerControl)d;
            errorBannerControl.TextBlockError.Text = Convert.ToString(e.NewValue);
            errorBannerControl.UpdateControlHeight();
        }

        private void ErrorBannerControl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            // 控件宽度变化时可能导致文本换行,重新计算高度
            UpdateControlHeight();
        }

        private void ErrorBannerControl_Loaded(object sender, RoutedEventArgs e)
        {
            // 初始化时计算高度
            UpdateControlHeight();
        }

        // 核心高度计算逻辑
        private void UpdateControlHeight()
        {
            if (TextBlockError == null || !IsLoaded) return;

            // 等待TextBlock布局更新完成后获取实际行数
            Dispatcher.InvokeAsync(() =>
            {
                int lineCount = TextBlockError.LineCount;
                if (lineCount <= 1)
                {
                    Height = 40;
                    ErrorScrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
                }
                else if (lineCount == 2)
                {
                    Height = 52;
                    ErrorScrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
                }
                else
                {
                    Height = 64;
                    ErrorScrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
                }
            }, System.Windows.Threading.DispatcherPriority.Loaded);
        }
    }
}

主要改动点:

  • 修正了依赖属性CLR包装的错误实现,避免绑定场景下赋值失效
  • 新增UpdateControlHeight方法,根据文本实际行数匹配对应的阶梯高度,同时控制滚动条显隐
  • 新增文本变更、控件宽度变化、初始化三个场景的高度计算触发逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 09:45:01