WPF 文本框和滚动行为

Posted

技术标签:

【中文标题】WPF 文本框和滚动行为【英文标题】:WPF TextBox and Scroll behavior 【发布时间】:2010-09-28 00:20:07 【问题描述】:

我有问题。 我需要在 ScrollViewer 中使用控件托管网格,以防止文本框在 UI 处被截断或折叠为零。我还希望在用户更改窗口宽度时扩展文本框的 with。 我正在将 Window 的内容设置为以下代码

<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>

一切正常,但是当用户在 TextBox 中输入很长的文本时,文本框会被展开并出现水平滚动。 有没有什么简单的方法可以限制 TextBox 的最大宽度,并且只有在用户更改窗口大小时才允许它展开。

【问题讨论】:

【参考方案1】:

问题在于父元素为 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>

请注意,我们设置了自动调整大小元素(边框)的 Margin 属性。这很重要,因为如果未设置,则会出现循环:

    边框宽度自动调整为网格列宽 TextBox 宽度调整为 Border.ActualWidth 网格列宽调整为文本框宽度 + 文本框边距 边框宽度再次自动调整为网格列宽

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

【讨论】:

根据 Robert 的解决方案修改代码后,我发现将文本框的 MaxWidth 绑定到封闭元素很有用。对于某些应用程序,它似乎避免了无限调整大小循环的问题。 工作正常,但现在当窗口变小时,TextBox 保持大尺寸。有什么解决办法吗?【参考方案2】:

否 - 这是 wpf 的一个众所周知的问题,预计将在下一个版本中修复。谢谢

【讨论】:

【参考方案3】:

像这样覆盖TextBox.MeasureOverride 对我有用:

protected override Size MeasureOverride(Size constraint)

    Size origSize = base.MeasureOverride(constraint);
    origSize.Width = MinWidth;
    return origSize;

【讨论】:

你如何将 MinWidth 链接到封闭的列?

以上是关于WPF 文本框和滚动行为的主要内容,如果未能解决你的问题,请参考以下文章

检查多个组合框和文本框的内容

使用匹配的文本框和列值过滤表

从C#中的WPF组合框或文本框获取文本

WPF不能正常格式化按钮和文本框

自动滚动文本框到底部

在 wpf 中的自定义样式上,文本框的文本始终为空