gpt4 book ai didi

c# - WPF RichTextBox 语法高亮问题

转载 作者:太空狗 更新时间:2023-10-29 22:51:56 27 4
gpt4 key购买 nike

大家好,我一直在开发一个带有文本编辑器的 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);
}
}

任何建议或帮助将不胜感激,提前致谢。

最佳答案

你应该高亮关键字,直到所有的文本都被解析,在每个Run中高亮关键字会影响对navigator.GetNextContextPosition的调用,导致意外的错误,比如firing textchanged重复事件。

在您突出显示关键字后,您在该关键字后键入的文本会继承该关键字的样式。一种解决方法是在突出显示关键字之前对整个文本调用 ClearAllProperties

下面是更新后的 txtStatus_TextChangedCheckWordsInRun 方法。

List<Tag> m_tags = new List<Tag>(); 
internal void CheckWordsInRun(Run theRun) //do not hightlight keywords in this method
{
//How, let's go through our text and save all tags we have to save.
int sIndex = 0;
int eIndex = 0;

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(text.Length, LogicalDirection.Backward); //fix 1
t.Word = lastWord;
m_tags.Add(t);
}
}

private void txtStatus_TextChanged(object sender, TextChangedEventArgs e)
{
if (txtStatus.Document == null)
return;
txtStatus.TextChanged -= txtStatus_TextChanged;

m_tags.Clear();

//first clear all the formats
TextRange documentRange = new TextRange(txtStatus.Document.ContentStart, txtStatus.Document.ContentEnd);
documentRange.ClearAllProperties();
//text = documentRange.Text; //fix 2

//Now let's create navigator to go though the text, find all the keywords but do not hightlight
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)
{
text = ((Run)navigator.Parent).Text; //fix 2
if (text != "")
CheckWordsInRun((Run)navigator.Parent);
}
navigator = navigator.GetNextContextPosition(LogicalDirection.Forward);
}

//only after all keywords are found, then we highlight them
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 { }
}
txtStatus.TextChanged += txtStatus_TextChanged;
}

关于c# - WPF RichTextBox 语法高亮问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17971300/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com