We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

Change format of words without changing selection.

I want to highlight certain words a color as the user types but having to first select them before doing so results in some buggy behavior while the user is typing quickly.  Is there any way to say find the word "person" and make it blue as the user is typing?  I've noticed the replace works perfectly, but I don't see a way to format while replacing.  I've also looked for the equivalent of TextRange, as that works great in a standard RTB, but can't seem to find it.  I'm essentially looking for a sort of syntax highlighting in the RichTextBoxAdv.

10 Replies

VM Venkatesan Mani Syncfusion Team July 5, 2017 12:15 PM UTC

Hi Kyle Steven Lewis,

Thank you for using Syncfusion products.

We can change the format of a specific word in SfRichTextBoxAdv control. This can be achieved through the search functionality of SfRichTextBoxAdv. For more information about the search functionality refer the following UG link.
UG link: https://help.syncfusion.com/wpf/sfrichtextboxadv/find-and-replace?cs-save-lang=1&cs-lang=csharp.

Please find a code snippet below to change the format using search functionality,


 
private void ChangeFormatAndReplaceWord(TextSearchResult lastResult, string wordToReplace) 
{ 
    if (lastResult == null) 
        return; 
 
    //Select the word. 
    richTextBoxAdv.Selection.Select(lastResult.Start, lastResult.End); 
 
    //Backup the highlight color. 
    HighlightColor highlightColor = HighlightColor.NoColor; 
    if (richTextBoxAdv.Selection.CharacterFormat.HighlightColor.HasValue) 
        highlightColor = richTextBoxAdv.Selection.CharacterFormat.HighlightColor.Value; 
    //Backup the bold value. 
    bool bold = richTextBoxAdv.Selection.CharacterFormat.Bold.HasValue ? richTextBoxAdv.Selection.CharacterFormat.Bold.Value : false; 
 
    //Set the flag to skip to avoid stack overflow, Since changing the selection format will apply the format to selected text and trigger the content changed event again. 
    isSkip = true; 
    //Change the format of selected word. 
    richTextBoxAdv.Selection.CharacterFormat.HighlightColor = HighlightColor.Blue; 
    richTextBoxAdv.Selection.CharacterFormat.Bold = true; 
 
 
    //Replace the text. 
    lastResult.Replace(wordToReplace); 
 
    //Move the cursor to selected word end. 
    richTextBoxAdv.Selection.Select(richTextBoxAdv.Selection.Start, richTextBoxAdv.Selection.Start); 
 
    //Restore the selection format 
    richTextBoxAdv.Selection.CharacterFormat.HighlightColor = highlightColor; 
    richTextBoxAdv.Selection.CharacterFormat.Bold = bold; 
    isSkip = false; 
} 
private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    string wordToHighlight = "person"; 
    TextPosition start = richTextBoxAdv.Document.GetTextPosition(richTextBoxAdv.Selection.Start.GetHierarchicalIndex); 
    TextSearchResults searchResults = richTextBoxAdv.FindAll(wordToHighlight, FindOptions.None); 
    if (searchResults != null && searchResults.Count > 0) 
    { 
        //Gets the found word one by one. 
 
        for (int i = 0; i < searchResults.Count; i++) 
        { 
            TextSearchResult result = searchResults[i]; 
            //if the text not equal, to skip the same word. 
            if (result.Text.Equals(wordToHighlight)) 
            { 
                ChangeFormatAndReplaceWord(result, wordToHighlight.ToUpper()); 
                i--; 
            } 
        } 
    } 
    //Reset the cursor. 
    richTextBoxAdv.Selection.Select(start, start); 
    richTextBoxAdv.Focus(); 
} 
 
 
Also, we can change the format of a specific word while the user typing the content in SfRichTextBoxAdv control. We can determine the content changes in SfRichTextBoxAdv by adding an event listener for ContentChanged event. In the content changed event using the search APIs we can find the last typed specific word and change the format of that word and replace with another word. Please find the code snippet below,


 
bool isSkip = false; 
private void richTextBoxAdv_ContentChanged(object obj, ContentChangedEventArgs args) 
{ 
    if (isSkip) 
        return; 
    string wordToHighlight = "person"; 
    TextPosition start = richTextBoxAdv.Document.GetTextPosition(richTextBoxAdv.Selection.Start.GetHierarchicalIndex); 
    TextSearchResults searchResults = richTextBoxAdv.FindAll(wordToHighlight, FindOptions.None); 
    if (searchResults != null && searchResults.Count > 0) 
    { 
        //Gets the last found word. 
        TextSearchResult lastResult = searchResults[searchResults.Count - 1]; 
        if (!lastResult.Text.Equals(wordToHighlight)) 
        { 
            //Reset the cursor. 
            richTextBoxAdv.Selection.Select(start, start); 
            return; 
        } 
        ChangeFormatAndReplaceWord(lastResult, wordToHighlight.ToUpper()); 
    } 
    richTextBoxAdv.Focus(); 
} 
 
Note: Handling format changes and replace operations in ContentChanged event handler will take reasonable time. Hence you may experience some delay in typing text.

We have also prepared a sample to demonstrate the same. please find the sample from following link.

Sample link:
sample.zip

Try the running sample and let us know if the sample helps you.


Regards,
Venkatesan M.  



KS Kyle Steven Lewis July 6, 2017 06:31 PM UTC

This works but still relies on selecting text with changes the caret position in the rich text box.  If the user is typing quickly and richTextBoxAdv.Selection.Select is ran, they will type over the highlighted text.



VM Venkatesan Mani Syncfusion Team July 7, 2017 12:23 PM UTC

Hi Kyle Steven Lewis,

Thank you for your update.

Our SfRichTextBoxAdv control methods are synchronous methods. So, the text will not be overwrite while changing the format of specific words in the ContentChanged event. As we mentioned in our previous update, you can experience some delay while typing the text. We can see that formatting is applied when typing quickly for other than specific words. So, we have modified the code to avoid the format overwrite for other than specific text. Please find the modified code and sample below,

sample code C#:

 
string startIndex; 
string endIndex; 
bool isSkip = false; 
/// <summary> 
/// Intializes the instance for MainWindow. 
/// </summary> 
public MainWindow() 
{ 
    InitializeComponent(); 
    richTextBoxAdv.ContentChanged += richTextBoxAdv_ContentChanged; 
    richTextBoxAdv.Focus(); 
} 
/// <summary> 
/// Change the format and replace the word. 
/// </summary> 
/// <param name="lastResult"></param> 
/// <param name="wordToReplace"></param> 
private void ChangeFormatAndReplaceWord(TextSearchResult lastResult, string wordToReplace) 
{ 
    if (lastResult == null) 
        return; 
 
    //Select the word. 
    richTextBoxAdv.Selection.Select(lastResult.Start, lastResult.End); 
 
    //Backup the highlight color. 
    HighlightColor highlightColor = HighlightColor.NoColor; 
    if (richTextBoxAdv.Selection.CharacterFormat.HighlightColor.HasValue) 
        highlightColor = richTextBoxAdv.Selection.CharacterFormat.HighlightColor.Value; 
    //Backup the bold value. 
    bool bold = richTextBoxAdv.Selection.CharacterFormat.Bold.HasValue ? richTextBoxAdv.Selection.CharacterFormat.Bold.Value : false; 
 
    //Set the flag to skip to avoid stack overflow, Since changing the selection format will apply the format to selected text and trigger the content changed event again. 
    isSkip = true; 
    //Change the format of selected word. 
    richTextBoxAdv.Selection.CharacterFormat.HighlightColor = HighlightColor.Blue; 
    richTextBoxAdv.Selection.CharacterFormat.Bold = true; 
 
 
    //Replace the text. 
    lastResult.Replace(wordToReplace); 
 
    //Reset the cursor to last user edited position. 
    richTextBoxAdv.Selection.Select(richTextBoxAdv.Document.GetTextPosition(startIndex), richTextBoxAdv.Document.GetTextPosition(endIndex)); 
 
    //Restore the selection format 
    richTextBoxAdv.Selection.CharacterFormat.HighlightColor = highlightColor; 
    richTextBoxAdv.Selection.CharacterFormat.Bold = bold; 
 
    isSkip = false; 
} 
/// <summary> 
/// Called when the button is clicked. 
/// </summary> 
/// <param name="sender"></param> 
/// <param name="e"></param> 
private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    string wordToHighlight = "person"; 
    startIndex = richTextBoxAdv.Selection.Start.GetHierarchicalIndex; 
    endIndex = richTextBoxAdv.Selection.End.GetHierarchicalIndex; 
    TextSearchResults searchResults = richTextBoxAdv.FindAll(wordToHighlight, FindOptions.None); 
    if (searchResults != null && searchResults.Count > 0) 
    { 
        //Gets the found word one by one. 
 
        for (int i = 0; i < searchResults.Count; i++) 
        { 
            TextSearchResult result = searchResults[i]; 
            //if the text not equal, to skip the same word. 
            if (result.Text.Equals(wordToHighlight)) 
            { 
                ChangeFormatAndReplaceWord(result, wordToHighlight.ToUpper()); 
                i--; 
            } 
        } 
    } 
    //Reset the cursor to last user edited position. 
    richTextBoxAdv.Selection.Select(richTextBoxAdv.Document.GetTextPosition(startIndex), richTextBoxAdv.Document.GetTextPosition(endIndex)); 
    richTextBoxAdv.Focus(); 
} 
/// <summary> 
/// Called when the rich text box adv content is changed. 
/// </summary> 
/// <param name="obj"></param> 
/// <param name="args"></param> 
private void richTextBoxAdv_ContentChanged(object obj, ContentChangedEventArgs args) 
{ 
    if (isSkip) 
        return; 
    startIndex = richTextBoxAdv.Selection.Start.GetHierarchicalIndex; 
    endIndex = richTextBoxAdv.Selection.End.GetHierarchicalIndex; 
    string wordToHighlight = "person"; 
    TextPosition start = richTextBoxAdv.Document.GetTextPosition(richTextBoxAdv.Selection.Start.GetHierarchicalIndex); 
    TextSearchResults searchResults = richTextBoxAdv.FindAll(wordToHighlight, FindOptions.None); 
    if (searchResults != null && searchResults.Count > 0) 
    { 
        //Gets the last found word. 
        TextSearchResult lastResult = searchResults[searchResults.Count - 1]; 
        if (!lastResult.Text.Equals(wordToHighlight)) 
        { 
            //Reset the cursor to last user edited position. 
            richTextBoxAdv.Selection.Select(richTextBoxAdv.Document.GetTextPosition(startIndex), richTextBoxAdv.Document.GetTextPosition(endIndex)); 
            return; 
        } 
        ChangeFormatAndReplaceWord(lastResult, wordToHighlight.ToUpper()); 
    } 
    richTextBoxAdv.Focus(); 
} 
 
 
Sample link:
Sample.zip.

Please try the running sample and let us know if this helps you.


Regards,
Venkatesan M. 



KS Kyle Steven Lewis July 8, 2017 06:12 AM UTC

My mistake, there was an implementation error on my end.  This works great, thank you!



VM Venkatesan Mani Syncfusion Team July 10, 2017 07:00 AM UTC

Hi Kyle Steven Lewis,

Thank you for your update.  
Please let us know if you require any further assistance on this. We will be happy to assist you.

Regards,
Venkatesan M. 



RO Robert May 3, 2018 04:05 PM UTC

Hi,
I need to select each word in my document with a certain color. I use this solution but it working slowly.

In a 7-page document, this works for several minutes. Perhaps this can be done faster?


VM Venkatesan Mani Syncfusion Team May 4, 2018 08:41 AM UTC

Hi Robert,

The mentioned solution in this forum is to change the format of specific text and replacing the specific text with another text while typing. This solution is provided using the ContentChanged Event handler. Changing the format and replacing the text achieved using the find and replace functionality. The find all method will search for the specific text in the whole document for each content changes and change the format of last found text. Hence, there will be reasonable delay while typing and delay time is directly proportional to the document content size.

Could you please explain your exact requirement? So that we can analyze specific to your requirement and provide you the optimized solution at the earlier.

Regards,
Venkatesan M. 



RO Robert May 4, 2018 12:18 PM UTC

So this is my task:
There is a large document. There is a list of words that is in the database.
I need to analyze and highlight all the words in the document.

This algorithm: if this word is in the database, I highlight it with a color (this is also in the database). If this word is not present - I highlight this word in yellow.
How do I solve this problem:

1. First I find all the unique words in the document.
2. I choose words from the database, if they are there under item 1.
3. I select words according to color.

This is the longest stage(3). Searching for each word and highlighting it with color works very long on large documents.

Can I single out the entire text first with one color? Is it possible to do it quickly? 
If this is possible, then this will speed up the solution of the problem. Or any of your suggestions.


VM Venkatesan Mani Syncfusion Team May 7, 2018 01:05 PM UTC

Hi Robert,

Thank you for your update.

We have prepared sample to achieve your requirement and attached in following link,

sample link:
Sample.zip

In the sample, we have achieved your requirements in a button click,
First solution (using find and multi selection):
“Search words and highlight” button click will highlight all the words (all the word highlighted in yellow) and search for the words present in the database (used local string collection) one by one. Highlight the words in green color.

Second solution:
“Analyze document and highlight” button click will highlight all the words extract the text word by word and check whether the word is present in the database (local string collection) and highlight if word exist.

As we mentioned in our earlier update, performing multiple actions as a single operation will take the reasonable time and the time is directly proportional to the document content size.

Regards,
Venkatesan M. 



RO Robert May 23, 2018 07:59 AM UTC

Thank you. This is great sample.

SIGN IN To post a reply.
Loader.
Live Chat Icon For mobile
Up arrow icon