Search a text in WPF RichTextBox & replace its font.
Hi,
I m using WPF RichTextBox(System.Windows.Controls.RichTextBox) but i am not getting a direct way to Search a specific word mentioned in RichTextBox & change its FontStyle.
Please help..!!
Answers
- Hi,
Here is a small sample in vb
<Grid> <RichTextBox Height="165" Margin="27,12,62,85" Name="RichTextBox1" Width="189" /> <Button Height="23" Margin="82,0,121,20" Name="Button1" VerticalAlignment="Bottom">Button</Button> </Grid>
Class Window1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click Dim objtextRange As TextRange Dim lstWordstoBeMatched As New List(Of String) lstWordstoBeMatched.Add("Hello") lstWordstoBeMatched.Add("to") Dim objWordStartPoint As TextPointer Dim objWordEndPoint As TextPointer objtextRange = New TextRange(RichTextBox1.Document.ContentStart, RichTextBox1.Document.ContentEnd) Dim strText As String strText = objtextRange.Text Dim lstMatchGroup As MatchCollection Dim objStart As TextPointer objStart = RichTextBox1.Document.ContentStart For Each strMatch In lstWordstoBeMatched lstMatchGroup = Regex.Matches(strText, strMatch) For Each objMatch As Match In lstMatchGroup objWordStartPoint = GoToPoint(objStart, objMatch.Index) objWordEndPoint = GoToPoint(objStart, objMatch.Index + objMatch.Length) objtextRange = New TextRange(objWordStartPoint, objWordEndPoint) objtextRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold) Next Next End Sub Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded RichTextBox1.Document.Blocks.Clear() Dim obj As New Paragraph obj.Inlines.Add("Hello weelcome to the program.Hello how are you.to the message") RichTextBox1.Document.Blocks.Add(obj) End Sub Public Function GoToPoint(ByVal start As TextPointer, ByVal x As Integer) As TextPointer Dim out As TextPointer = start Dim i As Integer = 0 Do While i < x If out.GetPointerContext(LogicalDirection.Backward) = TextPointerContext.Text Or _ out.GetPointerContext(LogicalDirection.Backward) = TextPointerContext.None Then i += 1 End If If out.GetPositionAtOffset(1, LogicalDirection.Forward) Is Nothing Then Return out Else out = out.GetPositionAtOffset(1, LogicalDirection.Forward) End If Loop Return out End Function End ClassHere I am entering the sample text in the code behind and the list of words to be made bold also .
Whatever is passed in the list will be make bold.
Hope it helps
Please mark posts as answers/helpful if it answers your query. This would be helpful for others facing the same kind of problem- Marked As Answer byRikz Saturday, November 07, 2009 9:17 AM
All Replies
Operating on the FlowDocument behind the RichTextBox works for me.
In the piece of code below, chatTextBox is a RichTextBox. DisplayMessage receives a message from a network socket, I'm not sure if the use of Dispatcher.Invoke is required in all situations, but it is in mine.
Each time I receive a message, I create a new Paragraph for it and append it to the text in the RTB. Whilst constructing the paragraph, I do any keyword colour replacements I wish to using regex.
The key is that a Paragraph is composed of a set of Run's. To change the FontStyle (Foreground colour in my case), you need to create a Run within the Run, so the XAML will go from <Run>Some text with blue text</Run> to <Run>Some text with </Run><Run Foreground="Blue">blue</Run><Run> text</Run>, where blue is the keyword, and Blue is the colour name.
There may be an easier way.. but it works for me...public partial class MainWindow : Window { private FlowDocument chatDoc; public MainWindow() { InitializeComponent(); chatDoc = new FlowDocument(); chatDoc.SetValue(Paragraph.LineHeightProperty, 1.0); } protected void DisplayMessage(string message) { try { this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new UpdatePublicChatDelegate(UpdateChat), message); } catch (Exception e) { Console.WriteLine(e.TargetSite.Name); Console.WriteLine(e.Message); } } public void UpdateChat(string text) { chatDoc.Blocks.Add(ChatDocument.CreateChatDocument(text)); this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new UpdateChatDocDelegate(UpdateChatDoc)); } public void UpdateChatDoc() { try { chatTextBox.Document = chatDoc; chatTextBox.ScrollToEnd(); } catch (Exception e) { Console.WriteLine(e.Message); throw; } } } public class ChatDocument { public static Paragraph CreateChatDocument(string text) { Paragraph para = new Paragraph(); para.Inlines.Add(CreateChatRun(text)); ReplaceKeywords(ref para); return para; } public static Run CreateChatRun(string text) { try { Color runColour = ClientSettings.Appearance.MessageText.Colour; Run chatRun = new Run(text); chatRun.Foreground = new SolidColorBrush(runColour); return chatRun; } catch (Exception e) { Console.WriteLine(e.Message); } return null; } public static void ReplaceKeywords(ref Paragraph para) { try { TextRange tr; string xamlString = TextRangeToXamlString(para, out tr); string curKeyword = string.empty; System.Text.RegularExpressions.MatchEvaluator CatchRun = delegate(System.Text.RegularExpressions.Match m) { string prepend = ""; string append = ""; if (m.Groups["prepend"].Length != 0) { prepend = m.Groups["prepend"].Value + "</Run>"; } if (m.Groups["append"].Length != 0) { append = "<Run>" + m.Groups["append"].Value; } return String.Format("{0}<Run Foreground=\"" + ClientSettings.Keywords[curKeyword].ToString() + "\">{1}</Run>{2}", prepend, curKeyWord, append); }; int replacementStartPos = xamlString.IndexOf("<Run>"); foreach (KeyValuePair<string, Color> keyword in ClientSettings.Keywords) { curKeyword = keyword.Key; string regexMatch = @"(?<prepend>.*)" + System.Text.RegularExpressions.Regex.Escape(keyword.Key) + "(?<append>.*)"; System.Text.RegularExpressions.Regex findLocalNick = new System.Text.RegularExpressions.Regex(regexMatch, System.Text.RegularExpressions.RegexOptions.IgnoreCase); xamlString = findLocalNick.Replace(xamlString, CatchRun, 1000, replacementStartPos); } xamlString = xamlString.Replace("<Run></Run>", ""); XamlStringToTextRange(ref tr, xamlString); } catch (Exception e) { Console.WriteLine(e.Message); } } private static string TextRangeToXamlString(Paragraph para, out TextRange tr) { tr = new TextRange(para.ContentStart, para.ContentEnd); System.IO.MemoryStream ms = new System.IO.MemoryStream(); tr.Save(ms, DataFormats.Xaml); return Encoding.UTF8.GetString(ms.ToArray()); } private static void XamlStringToTextRange(ref TextRange tr, string xamlString) { System.IO.MemoryStream msOut = new System.IO.MemoryStream(); System.IO.StreamWriter sw = new System.IO.StreamWriter(msOut); sw.Write(xamlString); sw.Flush(); msOut.Seek(0, System.IO.SeekOrigin.Begin); tr.Load(msOut, DataFormats.Xaml); } }
Thanks for replying bt m not familiar with C#.
I converted the code to VB.Net but its dificult for me to simulate..
I will explain my requirment once more.
my application is in WPF(VB.NET)
I will be having one list of Names(lstOfNames)
wen my screen gets displayed i will be havin one paragraph inside the RICHTEXTBOX(System.Windows.Controls.RichTextBox)
<RichTextBox Height="50" Name="rtb" Width="212" Margin="139,37,127,37" />
Now wat i need to do is if paragraph contains any name dat is in lstOfNames as well then change its fontstyle(either color/background) & then display it in RICHTEXTBOX- Hi,
Here is a small sample in vb
<Grid> <RichTextBox Height="165" Margin="27,12,62,85" Name="RichTextBox1" Width="189" /> <Button Height="23" Margin="82,0,121,20" Name="Button1" VerticalAlignment="Bottom">Button</Button> </Grid>
Class Window1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click Dim objtextRange As TextRange Dim lstWordstoBeMatched As New List(Of String) lstWordstoBeMatched.Add("Hello") lstWordstoBeMatched.Add("to") Dim objWordStartPoint As TextPointer Dim objWordEndPoint As TextPointer objtextRange = New TextRange(RichTextBox1.Document.ContentStart, RichTextBox1.Document.ContentEnd) Dim strText As String strText = objtextRange.Text Dim lstMatchGroup As MatchCollection Dim objStart As TextPointer objStart = RichTextBox1.Document.ContentStart For Each strMatch In lstWordstoBeMatched lstMatchGroup = Regex.Matches(strText, strMatch) For Each objMatch As Match In lstMatchGroup objWordStartPoint = GoToPoint(objStart, objMatch.Index) objWordEndPoint = GoToPoint(objStart, objMatch.Index + objMatch.Length) objtextRange = New TextRange(objWordStartPoint, objWordEndPoint) objtextRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold) Next Next End Sub Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded RichTextBox1.Document.Blocks.Clear() Dim obj As New Paragraph obj.Inlines.Add("Hello weelcome to the program.Hello how are you.to the message") RichTextBox1.Document.Blocks.Add(obj) End Sub Public Function GoToPoint(ByVal start As TextPointer, ByVal x As Integer) As TextPointer Dim out As TextPointer = start Dim i As Integer = 0 Do While i < x If out.GetPointerContext(LogicalDirection.Backward) = TextPointerContext.Text Or _ out.GetPointerContext(LogicalDirection.Backward) = TextPointerContext.None Then i += 1 End If If out.GetPositionAtOffset(1, LogicalDirection.Forward) Is Nothing Then Return out Else out = out.GetPositionAtOffset(1, LogicalDirection.Forward) End If Loop Return out End Function End ClassHere I am entering the sample text in the code behind and the list of words to be made bold also .
Whatever is passed in the list will be make bold.
Hope it helps
Please mark posts as answers/helpful if it answers your query. This would be helpful for others facing the same kind of problem- Marked As Answer byRikz Saturday, November 07, 2009 9:17 AM
- Tx.! :)
- Hi,
See this link too for some help on it
Hope it helps
Please mark posts as answers/helpful if it answers your query. This would be helpful for others facing the same kind of problem


