2013-07-31 1 views
5

안녕하세요. 텍스트 편집기가있는 WPF 응용 프로그램에서 작업 한 모든 사람들이 텍스트 편집기는 일부 토큰 (키워드) 위에 스타일이나 색을 적용하여이를 강조 표시하고 분명하게 나타내야합니다. 문제는 내가 아주 열심히 노력했지만 여전히 사용자가 키워드 중 하나를 입력 할 때 동일한 결과를 얻는다. "C#"에 "string"키워드를 입력하면 전체 텍스트가 파란색으로 표시됩니다. ,WPF RichTextBox 구문 강조 표시 문제

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); 
     } 
    } 
어떤 조언이나 손이 크게 감사합니다

입니다 :

이 내가 사용하는 코드였다 , 미리 감사드립니다. 모든 텍스트를 구문 분석 할 때까지

답변

6

당신은 반복의 TextChanged 이벤트를 트리거와 같은 예기치 않은 오류가 발생, navigator.GetNextContextPosition로 호출에 영향을 미치는 각 Run의 키워드를 강조 키워드를 강조한다.

키워드를 강조한 후에 해당 키워드 뒤에 입력 한 텍스트는 해당 키워드의 스타일을 그대로 유지합니다. 한 가지 해결 방법은 키워드를 밝히기 전에 전체 텍스트에 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; 
} 
+1

yessssssssssssssssss, 내 마음에서 대단히 감사합니다. 나는 네 손에 정말 감사한다. – a7madx7

+0

난 여전히 여기에 약간의 문제가있어, 때마다 내가 반환 (입력)을 치고 코드가 잘못된 위치에 잘못된 단어 hilight 시작 새 줄에 쓰기! – a7madx7

+2

@ Dr.Ahmed 오, 나는 새로운 라인으로 테스트하지 않았다 ... 글쎄, 내 대답을 참조하십시오 (수정 1 및 수정 2로 표시). – kennyzx