WPF 文本框和滚动行为

发布于 2024-09-14 04:24:49 字数 1139 浏览 13 评论 0原文

我有一个问题。 我需要在 ScrollViewer 中托管带有控件的网格,以防止文本框在 UI 上被截断或折叠为零。另外,我希望当用户更改窗口宽度时扩展文本框。 我将 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 最大宽度并仅在用户更改窗口大小时才允许其扩展。

I have a problem.
I need to host grid with controls in ScrollViewer to prevent textbox from being either truncated or collapsed to zero-with at the UI. Also I want the with of textbox to be expanded when user change windows width.
I'm setting Window's content to following code

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

All work fine, but when user types very long text in TextBox it is being expanded and horizontal scroll appears.
Is there any easy way to limit TextBox maximum width and allow it to be expanded only when user changes window size.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷默言语 2024-09-21 04:24:49

问题在于,父元素为 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 属性。 这很重要,因为如果如果未设置,则会出现循环:

  1. Border width autosizes to Grid column width
  2. TextBox width resizes to Border.ActualWidth
  3. Grid column width resizes to TextBox width + TextBox margin
  4. Border width autosizes to Grid column width again

将边距设置为与TextBox 的大小调整不会影响 Grid 的大小。

The problem is that the parent elements are providing TextBox with as much space as it thinks it needs, and when more text is present it will expand instead of staying at the initial automatic size.

One solution here is to make another auto-sized element and bind the TextBox.Width to it:

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

Note that we set the Margin property of the auto-sizing element (the Border). This is important because if it's not set, there will be a loop:

  1. Border width autosizes to Grid column width
  2. TextBox width resizes to Border.ActualWidth
  3. Grid column width resizes to TextBox width + TextBox margin
  4. Border width autosizes to Grid column width again

By setting the Margin to the same as the TextBox, the resizing of the TextBox won't affect the Grid size.

泪之魂 2024-09-21 04:24:49

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

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

Overriding TextBox.MeasureOverride like so worked for me:

protected override Size MeasureOverride(Size constraint)
{
    Size origSize = base.MeasureOverride(constraint);
    origSize.Width = MinWidth;
    return origSize;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文