简体   繁体   中英

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?

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

Choose a mono spaced font. And calculate the width of your textbox that has 60 chars.

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. If that's the case you should make an event that subscribes to the TextChanged event on the TextBox . 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. 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 . 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.

I've managed to set the maximum characters per line while the TextWrapping property is set to 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.

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:

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.

EDIT This doesn't work with wpf textboxes, only windows forms textboxes

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.

        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;

            }

        };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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