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.
You have exception because you have recursive call at the place lineText.ApplyPropertyValue(TextElement.ForegroundProperty
this call does modify your text. To avoid it you can simply add the flag:
bool changeIsRunning = false;
private void RichTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if(changeIsRunning)
{
return;
}
changeIsRunning = true;
try
{
//Put your logic here.
}
finally
{
changeIsRunning = false;
}
}
Be aware, that there are not only visible text, but also invisible element tags in the text(eg for the color).
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.