大家好,我一直在开发一个WPF应用程序,其中包含一个文本编辑器。这个文本编辑器应该对某些标记(关键字)应用一些样式或颜色,以突出显示并使其更加明显。但问题是,我已经非常努力地尝试了,但仍然得到相同的结果,即当用户输入其中一个关键字时,该关键字后面的整个文本都会被样式化!想象一下,如果你在“C#”中输入“string”关键字,那么它后面的整个文本都将变成蓝色。
以下是我使用的代码:
以下是我使用的代码:
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;
}
这里是文本更改事件处理程序
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);
}
}
任何建议或帮助都将不胜感激,提前致谢。