Hello everyone I've been working on a WPF application that has a text editor this text editor should apply some styling or colorizing over some tokens (keywords) to highlight it and make it obvious,,, the problem is i tried very very hard but i still get the same result which is when the user enters one of the keywords the whole text after that keyword is being styled ! just imagine if you types the " string " keyword in " C# " the whole text after it will be colored blue.
this was the code i used:
static List<string> tags = new List<string>(); static List<char> specials = new List<char>(); static string text; #region ctor static MainWindow() { string[] specialWords = { "string", "char", "null" }; tags = new List<string>(specialWords); // We also want to know all possible delimiters so adding this stuff. char[] chrs = { '.', ')', '(', '[', ']', '>', '<', ':', ';', '\n', '\t', '\r' }; specials = new List<char>(chrs); } public MainWindow() { InitializeComponent(); } #endregion //Now I should check statically if the string I passed is legal and constants in my dictionary public static bool IsKnownTag(string tag) { return tags.Exists(delegate(string s) { return s.ToLower().Equals(tag.ToLower()); }); } private static bool GetSpecials(char i) { foreach (var item in specials) { if (item.Equals(i)) { return true; } } return false; } // Wow. Great. Now I should separate words, that equals to my tags. For this propose we'll create new internal structure named Tag. This will help us to save words and its' positions. new struct Tag { public TextPointer StartPosition; public TextPointer EndPosition; public string Word; } internal void CheckWordsInRun(Run theRun){ //How, let's go through our text and save all tags we have to save. int sIndex = 0; int eIndex = 0; List<Tag> m_tags = new List<Tag>(); for (int i = 0; i < text.Length; i++) { if (Char.IsWhiteSpace(text[i]) | GetSpecials(text[i])) { if (i > 0 && !(Char.IsWhiteSpace(text[i - 1]) | GetSpecials(text[i - 1]))) { eIndex = i - 1; string word = text.Substring(sIndex, eIndex - sIndex + 1); if (IsKnownTag(word)) { Tag t = new Tag(); t.StartPosition = theRun.ContentStart.GetPositionAtOffset(sIndex, LogicalDirection.Forward); t.EndPosition = theRun.ContentStart.GetPositionAtOffset(eIndex + 1, LogicalDirection.Backward); t.Word = word; m_tags.Add(t); } } sIndex = i + 1; } } //How this works. But wait. If the word is last word in my text I'll never hightlight it, due I'm looking for separators. Let's add some fix for this case string lastWord = text.Substring(sIndex, text.Length - sIndex); if (IsKnownTag(lastWord)) { Tag t = new Tag(); t.StartPosition = theRun.ContentStart.GetPositionAtOffset(sIndex, LogicalDirection.Forward); t.EndPosition = theRun.ContentStart.GetPositionAtOffset(eIndex + 1, LogicalDirection.Backward); t.Word = lastWord; m_tags.Add(t); } //How I have all my words and its' positions in list. Let's color it! Dont forget to unsubscribe! text styling fires TextChanged event. txtStatus.TextChanged -= txtStatus_TextChanged; for (int i = 0; i < m_tags.Count; i++) { try { TextRange range = new TextRange(m_tags[i].StartPosition, m_tags[i].EndPosition); range.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Blue)); range.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold); } catch { } } m_tags.Clear(); txtStatus.TextChanged += txtStatus_TextChanged; }
and here is the text changed event handler
private void txtStatus_TextChanged(object sender, TextChangedEventArgs e) { if (txtStatus.Document == null) return; TextRange documentRange = new TextRange(txtStatus.Document.ContentStart, txtStatus.Document.ContentEnd); //documentRange.ClearAllProperties(); text = documentRange.Text; //Now let's create navigator to go though the text and hightlight it TextPointer navigator = txtStatus.Document.ContentStart; while (navigator.CompareTo(txtStatus.Document.ContentEnd) < 0) { TextPointerContext context = navigator.GetPointerContext(LogicalDirection.Backward); if (context == TextPointerContext.ElementStart && navigator.Parent is Run) { CheckWordsInRun((Run)navigator.Parent); } navigator = navigator.GetNextContextPosition(LogicalDirection.Forward); } }
Any advice or hand will be greatly appreciated,, thanks in advance.