WPF TextBox和滚动行为

12

我有一个问题。 我需要在ScrollViewer中托管带有控件的网格,以防止文本框被裁剪或在UI中折叠为零宽度。此外,当用户更改窗口宽度时,我希望文本框的宽度可以自动调整。 我将窗口内容设置为以下代码

<DockPanel>
    <TreeView DockPanel.Dock="Left" Width="150"/>
    <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <TextBlock Text="Name" 
                       Margin="5" 
                       VerticalAlignment="Center"/>
            <TextBox Grid.Column="1"
                     Text="Some Name"
                     Margin="5"
                     VerticalAlignment="Center"
                     MinWidth="200"/>
        </Grid>
    </ScrollViewer>
</DockPanel>

所有工作都很好,但是当用户在文本框中输入非常长的文本时,它会被扩展,并且会出现水平滚动条。 是否有一种简单的方法来限制文本框的最大宽度,并允许它仅在用户更改窗口大小时扩展。

2个回答

38

问题在于父元素给TextBox提供了它认为需要的所有空间,当存在更多文本时,它会扩展而不是保持初始的自动大小。

这里的一个解决方案是创建另一个自动大小的元素,并将TextBox.Width绑定到它:

<DockPanel>
    <TreeView Width="150" DockPanel.Dock="Left"/>
    <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <TextBlock Margin="5" VerticalAlignment="Center" Text="Name"/>
            <Border x:Name="b" Grid.Column="1" Margin="5"/>
            <TextBox Width="{Binding ActualWidth, ElementName=b}"
                     MinWidth="200"
                     Grid.Column="1"
                     Margin="5"
                     VerticalAlignment="Center"
                     Text="Some Name"/>
        </Grid>
    </ScrollViewer>
</DockPanel>

请注意,我们设置了自动调整大小元素(即 Border)的 Margin 属性。这很重要,因为如果未设置,将会产生一个循环:

  1. 边框宽度自适应于网格列宽度
  2. 文本框宽度调整为 Border.ActualWidth
  3. 网格列宽度调整为 TextBox 宽度 + TextBox margin
  4. 边框宽度再次自适应于网格列宽度

通过将 Margin 设置为与 TextBox 相同,TextBox 的调整大小不会影响网格大小。


1
在根据罗伯特解决方案调试代码后,我发现将文本框的MaxWidth绑定到包含元素是有用的。对于某些应用程序,它似乎可以避免无限调整大小循环的问题。 - estanford
3
运行正常,但当窗口变小时,文本框仍保持其大尺寸。有解决方法吗? - Heinzi

2

我曾尝试重写TextBox.MeasureOverride方法,以下是我的实现:

protected override Size MeasureOverride(Size constraint)
{
    Size origSize = base.MeasureOverride(constraint);
    origSize.Width = MinWidth;
    return origSize;
}

你如何将MinWidth与封闭的列链接起来? - H H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接