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

WPF中Grid容器内TextWrapping不生效问题求助

WPF ErrorTemplate中TextBlock宽度不随窗口调整的解决方案

问题描述

编写的WPF代码中,ErrorTemplate内的TextBlock未继承Grid的宽度,仅占用文本所需的最小宽度。需要实现TextBlock宽度随窗口大小动态调整,使文本自动换行。尝试将ErrorTemplate中的StackPanel替换为Grid后问题仍未解决。

相关代码

样式代码

<Style TargetType="PasswordBox" x:Key="passwordBoxStyle">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <StackPanel > <!--the only thing that worked for me was set stackpanel witdh to 300-->
                    <AdornedElementPlaceholder />
                    <TextBlock TextWrapping="Wrap" HorizontalAlignment="Stretch" Margin="0,5,5,0" Text="{Binding [0].ErrorContent}" Foreground="Red"></TextBlock>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Background" Value="#F5F7F9" />
    <Setter Property="Foreground" Value="#767676" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="BorderBrush" Value="#F5F7F9" />
    <Setter Property="FontSize" Value="12" />
    <Setter Property="Padding" Value="10 10" />
    <Setter Property="VerticalAlignment" Value="Center" />

    <Setter Property="Margin" Value="0,10,10,10" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type PasswordBox}">
                <Border x:Name="border" CornerRadius="3" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="True">
                    <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="BorderBrush" TargetName="border" Value="#d9d9d9"/>
                    </Trigger>
                    <Trigger Property="Validation.HasError" Value="True">
                        <Setter Property="BorderBrush" Value="Red"></Setter>
                        <Setter Property="Margin" Value="0,10,5,50" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

窗口代码

<Window x:Class="Vistas.prueba"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:w="clr-namespace:Vistas"
        Title="prueba" Height="300" Width="500">
    <Grid Width="300" x:Name="gd" Background="Aqua">
      <TextBlock Grid.Row="0" Text="Contrasena" />
          <PasswordBox Name="txtContrasena" Grid.Row="1" Width="300" Style="{StaticResource passwordBoxStyle}" w:BoundPasswordBox.BoundPassword="{Binding Path=Usu_Contrasena, NotifyOnValidationError=True, ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

    </Grid>
</Window>

PasswordBox绑定辅助类代码

class BoundPasswordBox
{ 
        private static bool _updating = false;

       
        public static readonly DependencyProperty BoundPasswordProperty =
            DependencyProperty.RegisterAttached("BoundPassword",
                typeof(string),
                typeof(BoundPasswordBox),
                new FrameworkPropertyMetadata(string.Empty, OnBoundPasswordChanged));

       
        public static string GetBoundPassword(DependencyObject d)
        {
            return (string)d.GetValue(BoundPasswordProperty);
        }

        
        public static void SetBoundPassword(DependencyObject d, string value)
        {
            d.SetValue(BoundPasswordProperty, value);
        }

       
        private static void OnBoundPasswordChanged(
            DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            PasswordBox password = d as PasswordBox;
            if (password != null)
            {
                // Disconnect the handler while we're updating.
                password.PasswordChanged -= PasswordChanged;
            }

            if (e.NewValue != null)
            {
                if (!_updating)
                {
                    password.Password = e.NewValue.ToString();
                }
            }
            else
            {
                password.Password = string.Empty;
            }
            // Now, reconnect the handler.
            password.PasswordChanged += new RoutedEventHandler(PasswordChanged);
        }

       
        static void PasswordChanged(object sender, RoutedEventArgs e)
        {
            PasswordBox password = sender as PasswordBox;
            _updating = true;
            SetBoundPassword(password, password.Password);
            _updating = false;
        }

        
}

解决方案

问题核心在于ErrorTemplate所在的装饰层默认不受父容器宽度约束,需要显式将容器宽度绑定到AdornedElementPlaceholder对应的控件宽度。修改Validation.ErrorTemplate部分代码如下:

<Setter Property="Validation.ErrorTemplate">
    <Setter.Value>
        <ControlTemplate>
            <!-- 用Grid作为容器,并绑定宽度到AdornedElement的实际宽度 -->
            <Grid Width="{Binding ElementName=adornedPlaceholder, Path=ActualWidth}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <!-- 给AdornedElementPlaceholder命名,用于绑定宽度 -->
                <AdornedElementPlaceholder x:Name="adornedPlaceholder" Grid.Row="0"/>
                <!-- TextBlock无需额外设置HorizontalAlignment,默认继承Grid宽度 -->
                <TextBlock Grid.Row="1" 
                           TextWrapping="Wrap" 
                           Margin="0,5,5,0" 
                           Text="{Binding [0].ErrorContent}" 
                           Foreground="Red"/>
            </Grid>
        </ControlTemplate>
    </Setter.Value>
</Setter>

说明

  • AdornedElementPlaceholder代表被验证的PasswordBox,绑定它的ActualWidth可以让容器宽度和PasswordBox保持一致,随父Grid的宽度变化而动态调整。
  • 使用Grid并定义行布局,确保PasswordBox和错误提示文本垂直排列,同时TextBlock会自动继承Grid的宽度,实现文本自动换行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 20:14:54