防止文本框内的文本水平滚动

本文关键字:文本 水平 滚动 | 更新日期: 2023-09-27 18:15:35

我有一个WPF应用程序,它有几个TextBox元素。用户填写这些信息,然后应用程序打印它们。TextBoxes的问题是,如果你一直输入一个文本框,一旦你把它填完,文本就会开始水平滚动,为更多的字母腾出空间,你就看不到输入的前几个字母了。

我们决定,解决方案是防止用户输入更多的文本,将适合在文本框。最好的办法是什么?

我查看了TextBox属性,并没有看到任何可以直接做我想做的事情。第一个想法是将包装设置为Wrap。然后订阅PreviewTextInput事件,如果行数将超过1,则处理该事件而不添加新键入的文本。显然,你仍然可以通过粘贴文本来绕过它,但更大的问题是,它只适用于单行文本框,我需要它也适用于多行文本框。

有没有我错过的更好的方法?计算文本宽度,然后确保它小于文本框的宽度/高度(如何?)是一个更好的选择?或者另一种解决方案?

防止文本框内的文本水平滚动

这是我的最终解决方案,也适用于多行文本框。它甚至可以在粘贴文本时工作。唯一奇怪的是,当文本溢出时,我删除了尾随字符,如果您在文本框中间键入文本,这可能看起来很奇怪。我试着通过在CaretIndex的点上删除字符来解决这个问题,但它太复杂了。但除此之外,它做了我需要它做的事情。为了提高性能,你可以缓存GetLineHeight函数的结果,这样你只需要在每个TextBox调用它一次(EDIT -我也添加了代码)。

<TextBox Height="23" Width="120" TextWrapping="Wrap"  TextChanged="TextBoxTextChanged" AcceptsReturn="True"/>
private void TextBoxTextChanged(object sender, TextChangedEventArgs e)
{
    TextBox textBox = sender as TextBox;
    if (textBox == null)
        return;
    double textLineHeight = GetCachedTextLineHeight(textBox);
    int maxTextBoxLines = (int)(textBox.ViewportHeight / textLineHeight);
    while (textBox.LineCount > maxTextBoxLines) //if typed in text goes out of bounds
    {
        if (textBox.Text.Length > 0)
            textBox.Text = textBox.Text.Remove(textBox.Text.Length - 1, 1); //remove last character
        if (textBox.Text.Length > 0)
            textBox.CaretIndex = textBox.Text.Length;
    }
}
private double GetTextLineHeight(TextBox textBox)
{
    FormattedText formattedText = new FormattedText(
        "a",
        CultureInfo.CurrentUICulture,
        FlowDirection.LeftToRight,
        new Typeface(textBox.FontFamily, textBox.FontStyle, textBox.FontWeight, textBox.FontStretch),
        textBox.FontSize,
        Brushes.Black);
    return formattedText.Height;
}
#region Caching
Dictionary<TextBox, double> _cachedLineHeights = new Dictionary<TextBox, double>();
private double GetCachedTextLineHeight(TextBox textBox)
{
    if (!_cachedLineHeights.ContainsKey(textBox))
    {
        double lineHeight = GetTextLineHeight(textBox);
        _cachedLineHeights.Add(textBox, lineHeight);
    }
    return _cachedLineHeights[textBox];
}
#endregion

您正在寻找MaxLength属性。你必须对这个数字进行实验,因为你需要记住,你可以在一个W的空间里放入很多i。通常,当我调整textbox的大小时,我根据W的大小和设置最大长度,因为W是最宽的字符。

编辑:刚刚看到你想让它与多行文本框一起工作…在这种情况下,只需将其设置为换行,它就不会水平滚动。