WPF RichTextBox的语法高亮问题 [英] WPF RichTextBox Syntax Highlighting Issue

查看:251
本文介绍了WPF RichTextBox的语法高亮问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好我一直在工作,有一个文本编辑器WPF应用程序这一文本编辑器应该应用一些造型或着色过一些令牌(关键字)以突出显示它并使其明显,,,问题是我试过很很辛苦,但我仍然得到同样的结果,当用户输入关键字后,全文被称呼的关键字之一是!试想一下,如果你的类型的字符串关键字C#整段文字后,它会变成蓝色



这是我使用的代码:




 静态列表<串GT;标签=新的List<串GT;(); 
静态列表<&烧焦GT;特价=新的List<&烧焦GT;();
静态字符串文本;
#地区的构造函数
静态主窗口()
{
的String [] = specialWords {串,炭,空};
标签=新的List<串GT;(specialWords);
//我们也想知道所有可能的分隔符,因此添加这个东西。
的char [] CHRS = {
'。',
')',
'(',
'[',
']',
'>',
'<',
':',
';',
'\\\
',
'\\ \\t',
'\r'
};
特价=新的List<烧焦>(CHRS);
}
公共主窗口()
{
的InitializeComponent();
}
#endregion
//现在我应该静态检查,如果我传递的字符串是在我的字典
公共静态的法律和常量布尔IsKnownTag(字符串变量)
{
返回tags.Exists(委托(字符串s){返回s.ToLower()等于(tag.ToLower());});
}
私人静态布尔GetSpecials(CHAR I)
{
的foreach(以特价VAR项)
{
如果(item.Equals(I))
{
返回真;
}
}
返回false;
}
//哇。大。现在,我应该分开的话,那等于我的标签。对于这个建议,我们将创建一个名为标签的新的内部结构。这将帮助我们节省词和它的立场。
新的结构变量
{
公共TextPointer中StartPosition;
公共TextPointer EndPosition;
公共字符串字;
}
内部空隙CheckWordsInRun(运行theRun){
//如何,让我们通过我们的文字和保存我们必须保存所有标签。
INT SINDEX = 0;
INT eIndex = 0;
名单,LT;标签> m_tags =新的List<吊牌及GT;();
的for(int i = 0; I< text.Length;我++)
{
如果(Char.IsWhiteSpace(文[I])| GetSpecials(文[I]))
{
如果(我大于0和放大器;&安培;!(Char.IsWhiteSpace(文[I - 1])| GetSpecials(文[I - 1])))
{
eIndex = I - 1;
串字= text.Substring(SINDEX,eIndex - SINDEX + 1);
如果(IsKnownTag(字))
{
标签T =新标签();
t.StartPosition = theRun.ContentStart.GetPositionAtOffset(SINDEX,LogicalDirection.Forward);
t.EndPosition = theRun.ContentStart.GetPositionAtOffset(eIndex + 1,LogicalDirection.Backward);
t.Word =字;
m_tags.Add(T);
}
}
SINDEX = I + 1;
}
}
//如何工作的。可是等等。如果字是在我的文字最后一句话我永远不会hightlight它,因为我要找的分隔符。让我们添加一些修正这种情况下
串最后字= text.Substring(SINDEX,text.Length - SINDEX);
如果(IsKnownTag(最后字))
{
标签T =新标签();
t.StartPosition = theRun.ContentStart.GetPositionAtOffset(SINDEX,LogicalDirection.Forward);
t.EndPosition = theRun.ContentStart.GetPositionAtOffset(eIndex + 1,LogicalDirection.Backward);
t.Word =最后字;
m_tags.Add(T);
}
//我怎么有我的所有单词,并在列表中的位置。我们的颜色吧!不要忘了取消!文本样式火灾TextChanged事件。
txtStatus.TextChanged - = txtStatus_TextChanged;
的for(int i = 0; I< m_tags.Count;我++)
{

{
的TextRange范围=新的TextRange(m_tags [1]。中StartPosition,m_tags [I] .EndPosition);
range.ApplyPropertyValue(TextElement.ForegroundProperty,新的SolidColorBrush(Colors.Blue));
range.ApplyPropertyValue(TextElement.FontWeightProperty,FontWeights.Bold);
}
赶上{}
}
m_tags.Clear();
txtStatus.TextChanged + = txtStatus_TextChanged;
}




和这里的文字改变事件处理程序




 私人无效txtStatus_TextChanged(对象发件人,TextChangedEventArgs E)
{
如果(txtStatus.Document == NULL)
的回报;
的TextRange documentRange =新的TextRange(txtStatus.Document.ContentStart,txtStatus.Document.ContentEnd);
//documentRange.ClearAllProperties();
文本= documentRange.Text;
//现在,让我们创建导航去,虽然文字和hightlight它
TextPointer航海家= txtStatus.Document.ContentStart;
,而(navigator.CompareTo(txtStatus.Document.ContentEnd)小于0)
{
TextPointerContext背景= navigator.GetPointerContext(LogicalDirection.Backward);
如果(上下文== TextPointerContext.ElementStart&放大器;&放大器; navigator.Parent正在运行)
{
CheckWordsInRun((运行)navigator.Parent);
}
=导航navigator.GetNextContextPosition(LogicalDirection.Forward);
}
}




任何意见或用手将不胜感激,,谢谢提前。


解决方案

您要突出关键词,直到所有文本进行解析,突出在每个运行将影响调用 navigator.GetNextContextPosition ,从而导致意外的错误,如重复地触发TextChanged事件。

和你hightlight一个关键字后,你该关键字后键入文本继承关键字的风格。一种解决方法是调用 ClearAllProperties 对整个文本之前你HIGHT点燃的关键字。



以下是更新 txtStatus_TextChanged CheckWordsInRun 方法。

 列表<标记和GT; m_tags =新的List<吊牌及GT;(); 
内部空隙CheckWordsInRun(运行theRun)//不hightlight这种方法
{关键词
//如何,让我们通过我们的文字和保存我们必须保存所有标签。
INT SINDEX = 0;
INT eIndex = 0;

的for(int i = 0; I< text.Length;我++)
{
如果(Char.IsWhiteSpace(文[I])| GetSpecials(文字[我))
{
如果(我大于0和放大器;&安培;!(Char.IsWhiteSpace(文[I - 1])| GetSpecials(文[I - 1])))
{
eIndex = I - 1;
串字= text.Substring(SINDEX,eIndex - SINDEX + 1);
如果(IsKnownTag(字))
{
标签T =新标签();
t.StartPosition = theRun.ContentStart.GetPositionAtOffset(SINDEX,LogicalDirection.Forward);
t.EndPosition = theRun.ContentStart.GetPositionAtOffset(eIndex + 1,LogicalDirection.Backward);
t.Word =字;
m_tags.Add(T);
}
}
SINDEX = I + 1;
}
}
//如何工作的。可是等等。如果字是在我的文字最后一句话我永远不会hightlight它,因为我要找的分隔符。让我们添加一些修正这种情况下
串最后字= text.Substring(SINDEX,text.Length - SINDEX);
如果(IsKnownTag(最后字))
{
标签T =新标签();
t.StartPosition = theRun.ContentStart.GetPositionAtOffset(SINDEX,LogicalDirection.Forward);
t.EndPosition = theRun.ContentStart.GetPositionAtOffset(text.Length,LogicalDirection.Backward); //修复1
t.Word =最后字;
m_tags.Add(T);
}
}

私人无效txtStatus_TextChanged(对象发件人,TextChangedEventArgs E)
{
如果(txtStatus.Document == NULL)
返回;
txtStatus.TextChanged - = txtStatus_TextChanged;

m_tags.Clear();

//首先清除所有格式
的TextRange documentRange =新的TextRange(txtStatus.Document.ContentStart,txtStatus.Document.ContentEnd);
documentRange.ClearAllProperties();
//文本= documentRange.Text; //修复2

//现在,让我们创建导航去虽然文本,发现所有的关键字,但不hightlight
TextPointer航海家= txtStatus.Document.ContentStart;
,而(navigator.CompareTo(txtStatus.Document.ContentEnd)小于0)
{
TextPointerContext背景= navigator.GetPointerContext(LogicalDirection.Backward);
如果(上下文== TextPointerContext.ElementStart&放大器;&安培; navigator.Parent是运行)
{
文本=((运行)navigator.Parent)。文本; //修复2
如果(文=!)
CheckWordsInRun((运行)navigator.Parent);
}
=导航navigator.GetNextContextPosition(LogicalDirection.Forward);
}

//只找到了所有关键字后,然后我们强调他们(INT I = 0; I< m_tags.Count;我++)

{

{
的TextRange范围=新的TextRange(m_tags [I] .StartPosition,m_tags [I] .EndPosition);
range.ApplyPropertyValue(TextElement.ForegroundProperty,新的SolidColorBrush(Colors.Blue));
range.ApplyPropertyValue(TextElement.FontWeightProperty,FontWeights.Bold);
}
赶上{}
}
txtStatus.TextChanged + = txtStatus_TextChanged;
}


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.

解决方案

You should highlight the keywords until all the text is parsed, highlighting the keywords in each Run will affect the call to navigator.GetNextContextPosition, causing unexpected errors like firing textchanged event repeatedly.

And after you hightlight a keyword, the text you type after that keyword INHERITS the style of that keyword. One workaround is calling ClearAllProperties on the whole text before you hight light the keywords.

Below is the updated txtStatus_TextChanged and CheckWordsInRun method.

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;
}

这篇关于WPF RichTextBox的语法高亮问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆