I have a RichTextBox (RTB) and next to it a DataGrid (DG). A user can paste a list of IDs into the RTB to perform some bulk actions on them. In order that users can be aware if an ID they passed into the RTB isn't in the DG, I want to change the colour of the text.
This is what I have at the moment:
private void RichTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
//TODO: Enforce 13 character line limit and replace any delimiters with new line
//Get all text
RichTextBox rtb = (RichTextBox)sender;
TextRange textRange = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
//Split into lines
string[] rtbLines = textRange.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in rtbLines)
{
//remove comms, but could some others
line.Replace(",", "");
//Get the index of the start of an ID
int startPos = textRange.Text.IndexOf(line);
//this should be unncessary?
if (startPos > -1)
{
//Get a pointer to text we found
TextPointer tp = textRange.Start.GetPositionAtOffset(startPos, LogicalDirection.Backward);
//this should be unnecessary?
if (tp != null)
{
//Get the line start position
TextPointer tpLine = tp.GetLineStartPosition(0); //This throws StackOverflowException sometimes?
//Get start of next line
TextPointer testLineEnd = tp.GetLineStartPosition(1);
//In case we're at the end, default to end of the document
TextPointer tpLineEnd = (testLineEnd ?? tp.DocumentEnd).GetInsertionPosition(LogicalDirection.Backward);
//Get text range between line start/end
TextRange lineText = new TextRange(tpLine, tpLineEnd);
//Cast the data and check if our text is in it so we can check it
if (UnassignedMPANsListView.ItemsSource != null && UnassignedMPANsListView.ItemsSource.Cast<CrmUnassignedMPAN>().ToList().Any(x => x.MPAN == line))
{
lineText.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red);
}
else
{
lineText.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
}
}
}
}
}
The issue is that often the line TextPointer tpLine = tp.GetLineStartPosition(0); causes a StackOverflowException. It seems to be only when the user is typing an ID; pasting seems to be OK.
My thought is that this is caused because the RichTextBox_TextChanged event is being called repeatedly, whereas pasting is a single hit, but I don't understand why that would cause this exception rather than just become very slow.
Also open to any other suggestions for how to implement this feature. My key requirements are that a user can paste a list, type them 1 by 1, and the rows can be programmatically coloured indepedently.