I am trying to limit the number of lines a user can enter in a textbox.
I have been researching - the closest I can find is this: Limit the max number of chars per line in a textbox .
And Limit the max number of chars per line in a textbox which turns out to be for winforms.
This isn't quite what I'm after... also worth mentioning that there is a misleading maxlines property which I have discovered only limits what is shown in the text box.
My requirements:
- Do not require the use of a mono-spaced font
- Limit the textbox to having a maximum of 5 lines
- Accepts carriage return
- Do not allow extra carriage returns
- Stops text input when max length has been reached
- Wraps text (don't particularly care if it does this in-between words or breaks up whole words)
- Handles text being pasted into the control and will only paste in what will fit.
- No scroll bars
- Also - and this would nice - having the option of limiting the number of characters per line
These requirements are for creating a WYSIWYG textbox which will be used for capturing data that will eventually be printed, and the fonts need to be changeable - if the text gets cut off or is too big for a fixed size line - then it will come out that way in print (even if it does not look right).
I've had a stab at doing this myself by handling events - but am having a great deal of trouble getting this right. Here is my code so far.
XAML
<TextBox TextWrapping="Wrap" AcceptsReturn="True"
PreviewTextInput="UIElement_OnPreviewTextInput"
TextChanged="TextBoxBase_OnTextChanged" />
Code Behind
public int TextBoxMaxAllowedLines { get; set; }
public int TextBoxMaxAllowedCharactersPerLine { get; set; }
public MainWindow()
{
InitializeComponent();
TextBoxMaxAllowedLines = 5;
TextBoxMaxAllowedCharactersPerLine = 50;
}
private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e)
{
TextBox textBox = (TextBox)sender;
int textLineCount = textBox.LineCount;
if (textLineCount > TextBoxMaxAllowedLines)
{
StringBuilder text = new StringBuilder();
for (int i = 0; i < TextBoxMaxAllowedLines; i++)
text.Append(textBox.GetLineText(i));
textBox.Text = text.ToString();
}
}
private void UIElement_OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
TextBox textBox = (TextBox)sender;
int textLineCount = textBox.LineCount;
for (int i = 0; i < textLineCount; i++)
{
var line = textBox.GetLineText(i);
if (i == TextBoxMaxAllowedLines-1)
{
int selectStart = textBox.SelectionStart;
textBox.Text = textBox.Text.TrimEnd('\r', '\n');
textBox.SelectionStart = selectStart;
//Last line
if (line.Length > TextBoxMaxAllowedCharactersPerLine)
e.Handled = true;
}
else
{
if (line.Length > TextBoxMaxAllowedCharactersPerLine-1 && !line.EndsWith("\r\n"))
e.Handled = true;
}
}
}
This doesn't quite work right - I am getting strange behaviour on the last line and the selected position within the textbox keeps jumping about.
As an aside, maybe I am going down the wrong track... I was also wondering if this could be achieved by using a regular expression using something like this: https://stackoverflow.com/a/1103822/685341
I am open to any ideas as I have been struggling with this for a while. The requirements listed above are immutable - I am unable to change them.