简体   繁体   English

限制文本框中每行的最大字符数

[英]Limit the max number of chars per line in a textbox

Say I have the following: 说我有以下内容:

<TextBox TextWrapping="Wrap" 
         AcceptsReturn="True" 
         AcceptsTab="True" 
         MaxLines="3000"/>

Is there a way I can limit the max number of chars per line to 60? 有没有办法可以将每行的最大字符数限制为60?

I have seen ways to do it via keydown events, but that does not seem to be foolproof (ie what about pasting in a long block of text). 我已经看到了通过keydown事件做到这一点的方法,但这似乎并不是万无一失的(即在长文本块中粘贴的内容)。

Choose a mono spaced font. 选择单声道间隔字体。 And calculate the width of your textbox that has 60 chars. 并计算具有60个字符的文本框的宽度。

Given that you're responding to keydown events I assume that you want to make sure that the string behind the TextBox adheres to the "60 chars per line" rule. 鉴于您正在响应keydown事件,我假设您要确保TextBox后面的字符串遵循“每行60个字符”规则。 If that's the case you should make an event that subscribes to the TextChanged event on the TextBox . 如果是这种情况,您应该在TextBox上创建一个订阅TextChanged事件的事件。 There you can fix up the text and either truncate or break apart lines that are too long. 在那里你可以修复文本,并截断或拆分太长的行。

(edit) To solve the display portion you can do as Kafuka suggested: just make the box wide enough to hold 60 characters, and use a monospaced font if you want to be sure. (编辑)要解决显示部分,你可以像Kafuka建议的那样:只需将盒子放宽到足以容纳60个字符,如果你想确定,可以使用等宽字体。 If you've made sure the string is correct this should fall into line easily. 如果你确定字符串是正确的,这应该很容易排成一行。

I do not really think that you can do this while wrapping because wrapping would change the current line to fit the TextBox . 我真的不认为你可以在包装时这样做,因为换行会改变当前行以适应TextBox Even while using Notepad , you can never view the Status Bar while enabling the Word Wrap as it will be difficult to get the current line index and its length while wrapping. 即使在使用记事本时 ,也无法在启用Word Wrap时查看状态栏 ,因为在行时很难获得当前行索引及其长度。

I've managed to set the maximum characters per line while the TextWrapping property is set to NoWrap . 我已设法设置每行的最大字符数,而TextWrapping属性设置为NoWrap You'll first need to get the length of the current line index. 您首先需要获取当前行索引的长度。 Then, in case it's 59 or more, handle the input. 然后,如果它是59或更多,处理输入。

Example

<TextBox Name="textBox1"
         TextWrapping="NoWrap" 
         AcceptsReturn="True" 
         AcceptsTab="True" 
         MaxLines="3000"
         KeyDown="textBox1_KeyDown"/>
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
    //Initialize a new int of name CurrentLine to get the current line the user is on
    int CurrentLine = textBox1.GetLineIndexFromCharacterIndex(textBox1.Text.Length);

    //Continue if the length of the current line is more or equal to 59
    if (textBox1.GetLineLength(CurrentLine) >= 59) 
    {
        //Don't insert the character
        e.Handled = true; 
    }
}

Thanks, 谢谢,
I hope you find this helpful :) 我希望这个对你有用 :)

I know this is an extremely late answer, but so that people who find this can get a good answer, with protection against for instance Ctrl+C and stuff: 我知道这是一个非常晚的答案,但是找到这个的人可以得到一个很好的答案,例如Ctrl + C和东西:

private void textBox1_TextChanged(object sender, EventArgs e)
{
    foreach (string line in textBox1.Lines)
    {
        if (line.Length > 60)
        {
            textBox1.Undo();
        }
    }

    textBox1.ClearUndo();
}

Note that this does mean you cannot use Ctrl+Z in the textbox anymore but if that doesn't bother you this is a good option, because it works with any font. 请注意,这确实意味着您不能再在文本框中使用Ctrl + Z,但如果这不打扰您,这是一个不错的选择,因为它适用于任何字体。

EDIT This doesn't work with wpf textboxes, only windows forms textboxes 编辑这不适用于wpf文本框,只有Windows形成文本框

I have looked at several solutions today. 我今天看了几个解决方案。 They either don't work at all, or if they work, they don't work the way I think they should. 他们要么根本不工作,要么他们工作,他们不按我认为应该的方式工作。 Oddities with cursor position, or wrapping incorrectly. 光标位置的奇数或包装不正确。 Here is my "solution", and I hope it helps someone in the future. 这是我的“解决方案”,我希望它能帮助将来的某个人。 It wraps, doesn't unwrap, and keeps any existing new lines. 它包装,不打开,并保留任何现有的新行。 I set this example to 60 characters wide, and a bool isBusyUpdating outside of this example to keep it from firing again when the update is in progress. 我将此示例设置为60个字符宽,并且在此示例之外使用bool isBusyUpdating以防止在更新进行时再次触发。

        txtNotes.HorizontalContentAlignment = HorizontalAlignment.Left;
        txtNotes.VerticalContentAlignment = VerticalAlignment.Top;
        txtNotes.TextWrapping = TextWrapping.NoWrap;
        txtNotes.AcceptsReturn = true;
        txtNotes.TextChanged += delegate (object o, TextChangedEventArgs args)
        {
            //args.Handled = true;
            TextBox thisText = (TextBox)args.Source;
             if (!isBusyUpdating)
            {
                isBusyUpdating = true;
                string updatedText = "";
                bool blnUpdate = false;
                int curPos = thisText.CaretIndex;

                foreach (string thisLine in thisText.Text.Split('\n'))
                {

                    if (thisLine.Length > 60)
                    {
                        blnUpdate = true;
                        updatedText = updatedText + 
                            thisLine.Substring(0, 60)
                            .Replace("\n", "") +
                                      "\n" + thisLine.Substring(60);
                        curPos++;
                    }
                    else
                    {
                        updatedText = updatedText + thisLine + "\n";
                    }
                }

                if (blnUpdate)
                {
                    thisText.Text = updatedText;
                    thisText.CaretIndex = curPos-1;
                }
                isBusyUpdating = false;

            }

        };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM