当文本不再适合一行时,如何配置TextBox控件以自动垂直自动调整大小?

Kla*_*Nji 12 wpf textbox autosize

TextBox当文本不再适合一行时,如何配置控件以自动垂直调整自身大小?

例如,在以下XAML中:

<DockPanel LastChildFill="True" Margin="0,0,0,0">
  <Border Name="dataGridHeader" 
    DataContext="{Binding Descriptor.Filter}"
    DockPanel.Dock="Top"                         
    BorderThickness="1"
    Style="{StaticResource ChamelionBorder}">
  <Border
    Padding="5"
    BorderThickness="1,1,0,0"                            
    BorderBrush="{DynamicResource {ComponentResourceKey TypeInTargetAssembly=dc:NavigationPane, 
    ResourceId={x:Static dc:NavigationPaneColors.NavPaneTitleBorder}}}">
    <StackPanel Orientation="Horizontal">
      <TextBlock                                
        Name="DataGridTitle"                                                                                                
        FontSize="14"
        FontWeight="Bold"                                    
        Foreground="{DynamicResource {ComponentResourceKey 
        TypeInTargetAssembly=dc:NavigationPane, 
        ResourceId={x:Static dc:NavigationPaneColors.NavPaneTitleForeground}}}"/>
      <StackPanel Margin="5,0"  Orientation="Horizontal" 
              Visibility="{Binding IsFilterEnabled, FallbackValue=Collapsed, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}"
              IsEnabled="{Binding IsFilterEnabled, FallbackValue=false}"  >                                    
          <TextBlock  />                                                                
          <TextBox    
            Name="VerticallyExpandMe"
            Padding="0, 0, 0, 0"  
            Margin="10,2,10,-1"                                                                                                                                                                                                                     
            AcceptsReturn="True"
            VerticalAlignment="Center"                                    
            Text="{Binding QueryString}"
            Foreground="{DynamicResource {ComponentResourceKey 
            TypeInTargetAssembly=dc:NavigationPane, 
            ResourceId={x:Static dc:NavigationPaneColors.NavPaneTitleForeground}}}">
          </TextBox>
        </StackPanel>                               
    </StackPanel>
  </Border>              
  </Border>
</DockPanel>
Run Code Online (Sandbox Code Playgroud)

TextBox名为"VerticallyExpandMe" 的控件需要在绑定到它的文本不适合一行时自动垂直展开.随着AcceptsReturn设置为true,TextBox垂直展开,如果我按在它进入,但我想它不自动执行此操作.

Ian*_*ths 43

尽管Andre Luus的建议基本上是正确的,但它实际上并不适用于此,因为你的布局会打败文本包装.我会解释原因.

从根本上说,问题是这样的:文本换行只在元素的宽度受约束时做任何事情,但是你的宽度是无约束的,TextBox因为它是水平的后代StackPanel.(好吧,两个水平堆栈面板.可能更多,取决于您采用您的示例的上下文.)由于宽度不受约束,TextBox因此不知道何时应该开始包装,因此它永远不会换行,即使你启用包装.你需要做两件事:约束它的宽度并启用包装.

这是一个更详细的解释.

您的示例包含许多与问题无关的详细信息.这是一个我稍微减少的版本,以便更容易解释错误:

<StackPanel Orientation="Horizontal">
    <TextBlock Name="DataGridTitle" />
    <StackPanel
        Margin="5,0"
        Orientation="Horizontal"
        >
        <TextBlock />
        <TextBox
            Name="VerticallyExpandMe"
            Margin="10,2,10,-1"
            AcceptsReturn="True"
            VerticalAlignment="Center"
            Text="{Binding QueryString}"
            >
        </TextBox>
    </StackPanel>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

所以我删除了你的包含DockPanelBorder内部的两个嵌套元素,因为它们既不是问题的一部分,也不是解决方案的相关内容.所以我从StackPanel你的例子中的一对嵌套元素开始.而且我还删除了大部分属性,因为大多数属性也与布局无关.

这看起来有点奇怪 - 有两个嵌套的水平堆栈面板看起来多余,但如果您需要在运行时使嵌套的可见或不可见,它确实在您的原始中有意义.但它更容易看到问题.

(空TextBlock标签也很奇怪,但这与原始标签完全一样.这似乎没有做任何有用的事情.)

这就是问题:你TextBox的内部是一些水平StackPanel元素,意味着它的宽度不受约束 - 你无意中告诉文本框它可以自由地增长到任何宽度,无论实际有多少空间.

A StackPanel将始终执行在堆叠方向上不受约束的布局.因此,当涉及到布局时TextBox,它将通过横向大小double.PositiveInfinity到达TextBox.所以人们TextBox总会认为它有更多的空间而不是它需要的空间.此外,当一个孩子StackPanel要求比实际可用的空间更多的空间,StackPanel谎言,并假装给它那么多的空间,但然后庄稼.

(这是你为极端简单所付出的代价StackPanel- 它简直到了骨头,因为它会愉快地构建实际上不适合的布局.你应该只使用StackPanel你真的有无限空间因为你在里面ScrollViewer,或者你确定你有足够的物品,你不会用完空间,或者你不关心面板末端的物品,当它们变得太大时你不希望布局系统尝试做任何比简单裁剪内容更聪明的事情.)

因此,打开文本包装在这里无济于事,因为它StackPanel总会假装文本的空间足够多.

您需要不同的布局结构.堆栈面板使用是错误的,因为它们不会强制执行文本换行所需的布局约束.

这是一个简单的例子,大致可以满足您的需求:

<Grid VerticalAlignment="Top">
    <DockPanel>
        <TextBlock
            x:Name="DataGridTitle"
            VerticalAlignment="Top"
            DockPanel.Dock="Left"
            />
        <TextBox
            Name="VerticallyExpandMe"
            AcceptsReturn="True"
            TextWrapping="Wrap"
            Text="{Binding QueryString}"
            >
        </TextBox>
    </DockPanel>
</Grid>
Run Code Online (Sandbox Code Playgroud)

如果您创建一个全新的WPF应用程序并将其作为主窗口的内容粘贴,您应该会发现它符合您的要求 - TextBox从一行开始,填充可用宽度,如果您键入文本,它就会'当你添加更多文本时,我会一次增长一行.

当然,布局行为总是对上下文敏感,因此将它放到现有应用程序的中间可能是不够的.如果将其粘贴到固定大小的空间(例如,作为窗口的主体),那将会起作用,但如果将其粘贴到宽度不受约束的上下文中,则无法正常工作.(例如,在ScrollViewer水平内部或水平内部StackPanel.)

因此,如果这对您不起作用,那将是因为您的布局中其他地方出现了其他错误 - 可能还有StackPanel其他更多元素.从你的例子来看,可能值得花一些时间考虑你在布局中真正需要的东西并简化它 - 负边距的存在,以及似乎没有做那些空的任何东西的元素TextBlock通常表示过于复杂的布局.布局中不必要的复杂性使得很难实现您正在寻找的效果.

  • 不知道如何表达我的谢意,但这是一个非常好的回应.你让我理解了这个问题,并提供了一个非常好的解决方案.是的,我应该在发布前稍微清理一下,因为它会分散注意力.将在下次学习.再次感谢. (7认同)

Eri*_*ngs 6

或者,你可以限制你TextBlockWidth被绑定到父母的ActualWidth,例如:

<TextBlock Width="{Binding ElementName=*ParentElement*, Path=ActualWidth}" 
           Height="Auto" />
Run Code Online (Sandbox Code Playgroud)

这将迫使它自动调整其高度.