WPF TextBlock highlight certain parts based on search condition

后端 未结 9 1151
遇见更好的自我
遇见更好的自我 2020-12-01 08:42

I have TextBlock that has Inlines dynamicly added to it (basically bunch of Run objects that are either italic or bold).

In my application I have search function.

9条回答
  •  半阙折子戏
    2020-12-01 08:55

    Here I present another Approach for highlighting text. I had a use case where I needed to decorate a bunch of C# Code in WPF, however I did not want to use textBlock.Inlines.Add type of syntax, instead I wanted to generate the highlighting XAML on the fly and then dynamically add it to a Canvas or some other container in WPF.

    So suppose you want to colorize the following piece of code and also highlight a part of it:

    public static void TestLoop(int count)
    { 
       for(int i=0;i

    Suppose the above code is found in a file called Test.txt . Suppose you want to colorize all the C# keywords (public, static, void etc..) and simple types(int, string) in Blue, and Console.WriteLine highlight in yellow.

    Step 0. Create a new WPF Application and include some sample code similar to above in a file called Test.txt

    Step 1. Create a Code Highlighter class:

    using System.IO;
    using System.Text;
    
    public enum HighLightType
    {
        Type = 0,
        Keyword = 1,
        CustomTerm = 2
    }
    
    public class CodeHighlighter
    {
        public static string[] KeyWords = { "public", "static", "void", "return", "while", "for", "if" };
        public static string[] Types = { "string", "int", "double", "long" };
    
        private string FormatCodeInXaml(string code, bool withLineBreak)
        {
            string[] mapAr = { "<","<" , //Replace less than sign
                                ">",">" }; //Replace greater than sign
            StringBuilder sb = new StringBuilder();
    
            using (StreamReader sr = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(code))))
            {
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();
    
                    line = line.Replace("\t", "    "); //Replace tabs
                    line = line.Replace(" ", " "); //Replace spaces
    
                    for (int i = 0; i < mapAr.Length; i += 2)
                        line = line.Replace(mapAr[i], mapAr[i + 1]);
    
                    if (withLineBreak)
                        sb.AppendLine(line + ""); //Replace line breaks
                    else
                        sb.AppendLine(line);
                }
    
            }
            return sb.ToString();
        }
    
    
        private string BuildForegroundTag(string highlightText, string color)
        {
            return "" + highlightText + "";
        }
    
        private string BuildBackgroundTag(string highlightText, string color)
        {
            return "" + highlightText + "";
        }
    
        private string HighlightTerm(HighLightType type, string term, string line)
        {
            if (term == string.Empty)
                return line;
    
            string keywordColor = "Blue";
            string typeColor = "Blue";
            string statementColor = "Yellow";
    
            if (type == HighLightType.Type)
                return line.Replace(term, BuildForegroundTag(term, typeColor));
            if (type == HighLightType.Keyword)
                return line.Replace(term, BuildForegroundTag(term, keywordColor));
            if (type == HighLightType.CustomTerm)
                return line.Replace(term, BuildBackgroundTag(term, statementColor));
    
            return line;
        }
    
        public string ApplyHighlights(string code, string customTerm)
        {
            code = FormatCodeInXaml(code, true);
            customTerm = FormatCodeInXaml(customTerm, false).Trim();
    
            StringBuilder sb = new StringBuilder();
            using (StreamReader sr = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(code))))
            {
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();
    
                    line = HighlightTerm(HighLightType.CustomTerm, customTerm, line);
    
                    foreach (string keyWord in KeyWords)
                        line = HighlightTerm(HighLightType.Keyword, keyWord, line);
    
                    foreach (string type in Types)
                        line = HighlightTerm(HighLightType.Type, type, line);
    
                    sb.AppendLine(line);
                }
            }
    
            return sb.ToString();
    
        }
    }
    

    Step 2. Add a Canvas XAML tag to your MainWindow.xaml

    
    
        
    
    

    Step 3. In Your WPF Application add the following code: (make sure that test.txt is in the correct location) :

    using System.Text;
    using System.IO;
    using System.Windows;
    using System.Windows.Markup;
    
    namespace TestCodeVisualizer
    {
        /// 
        /// Interaction logic for MainWindow.xaml
        /// 
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                string testText = File.ReadAllText("Test.txt");
                FrameworkElement fe = GenerateHighlightedTextBlock(testText, "Console.WriteLine");
                this.canvas.Children.Add(fe);
            }
    
    
            private FrameworkElement GenerateHighlightedTextBlock(string code, string term)
            {
                CodeHighlighter ch = new CodeHighlighter();
                string uc = "[CONTENT]";
    
                string content = "" + ch.ApplyHighlights(code, term) + "";
                uc = uc.Replace("[CONTENT]", content);
    
                FrameworkElement fe = XamlReader.Load(new System.IO.MemoryStream(Encoding.UTF8.GetBytes(uc))) as FrameworkElement;
                return fe;
            }
    
        }
    }
    

提交回复
热议问题