Search code examples
c#wpftextblocktextformat

WPF C# TextBlock. How to format textblock text programatically to format foreground color of certain words that are color names


Problem:
I have WPF TextBlock with dynamically changed text. This text contains words that are color names.
For example:

MyTextBlock.Text = "This is some dynamic text that contains red, green and yellow words inside it.";

Result should be rendered so all "red", "green" and "yellow" words are formatted with their color.


Note: Text is dynamically changed so static formatting is not an option.)

Solution

  • You can take benefit from Inline collection property inside TextBlock to customize the content and set it dynamically..

    <TextBlock
        x:Name="MyTextBlock"
        Height="100"
        Padding="8"
        FontSize="18"
        TextWrapping="Wrap" />
    

    You would do something like this in code behind..

    {
        InitializeComponent();
        var input = "This is some dynamic text that contains Red and green and yellow words inside it.";
        UpdateTextBoxWithColoredText(MyTextBlock, input, _colors);
    }
    

    Where UpdateTextBoxWithColoredText is

    private void UpdateTextBoxWithColoredText(TextBlock textBlock,
        string input, List<string> colors)
    {
        // textBlock.Text = ""; // empty the current text if needed
        var list = input
            .Split(' ')
            .ToList();
        var stringBuilder = new StringBuilder();
        foreach (var currentString in list)
        {
            if (colors.Contains(currentString.ToLower()))
            {
                textBlock.Inlines.Add($"{stringBuilder} ");
                stringBuilder.Clear();
                var run = new Run(currentString)
                {
                    Foreground = ColorName2Brush(currentString.ToLower())
                };
                textBlock.Inlines.Add(run);
            }
            else
                stringBuilder.Append(currentString);
            textBlock.Inlines.Add(" ");
        }
    
        textBlock.Inlines.Add(stringBuilder.ToString());
    }
    
    private readonly List<string> _colors = new() { "red", "green", "yellow" };
    
    private Brush ColorName2Brush(string colorName) =>
        colorName switch
        {
            "green" => ToSolidColorBrush("#00FF00"),
            "yellow" => ToSolidColorBrush("#FFFF00"),
            "red" => ToSolidColorBrush("#FF0000"),
            _ => ToSolidColorBrush("#000000")
        };
    
    private SolidColorBrush ToSolidColorBrush(string hex)
    {
        try
        {
            return (SolidColorBrush)new BrushConverter().ConvertFrom(hex);
        }
        catch (Exception)
        {
            return (SolidColorBrush)new BrushConverter().ConvertFrom("#000000");
        }
    }
    

    Sample output

    enter image description here

    Note: punctuations are not handled in the solution above, also linebreaks (you can do textblock.Inlines.Add(new LineBreak()); or stringBuilder.AppendLine();), this is sort of string processing that you can do it in your behalf :)