WPF text control with colors only

3.1k views Asked by At

I need a text control where the user is able to edit text and where some parts of the text can have different colors based on the text. Basically, imagine Visual Studio source file editor or any other source file editor which colors the source code. What WPF control is that? None of the three options in WPF I am aware of are not suitable:

TextBox doesn't allow colors

TextBlock doesn't allow users to edit the text

RichTextBox allows too much - I just want colors.

Maybe RichTextBox can have fixed other text formattings (i.e. fonts, bold, italic)? Any thoughts?

3

There are 3 answers

0
ReeganLourduraj On

This Feature is not in any of the text controls. May be you can write your own custom control by inheriting RichTextBox.

1
S.Spieker On

I think your best choice is looking for 3rd Party controls, as suggested by Erno.

For example: wpfsyntax

WPF Syntax Highlight Textbox is very simple control for editing source code. Contains line numbering, world highlighting, indenting (tab, shift+tab....) and more. Test application contains parser for language IronPython and Boo. Syntax Highlight Textbox is developed in C#.

Or: Fast colored textblox

For one of my projects, I have felt the need of a text editor with syntax highlighting. At first, I used a component inherited from RichTextBox, but while using it for a large amount of text I found out that RichTextBox highlights very slowly a large number of colored fragments (from 200 and more). When such highlighting has to be made in a dynamic way, it causes a serious problem.
Therefore I created my own text component which uses neither Windows TextBox nor RichTextBox.

3
Mario Vernari On

Here is a (very) rough example keeping stick with TextBox and TextBlock: just for fun, but worthwhile...

enter image description here

Here is the XAML...

<Grid>
    <TextBlock
        x:Name="Tx1"
        HorizontalAlignment="{Binding Path=HorizontalAlignment, ElementName=Tb1}"
        VerticalAlignment="{Binding Path=VerticalAlignment, ElementName=Tb1}"
        Margin="{Binding Path=Margin, ElementName=Tb1}"
        FontSize="{Binding Path=FontSize, ElementName=Tb1}"
        />

    <TextBox
        x:Name="Tb1"
        HorizontalAlignment="Stretch"
        VerticalAlignment="Center"
        Margin="100,0"
        FontSize="24"
        Background="Transparent"
        Foreground="Transparent"
        TextChanged="Tb1_TextChanged"
        />
</Grid>

...and here is some code...

    private void Tb1_TextChanged(object sender, TextChangedEventArgs e)
    {
        var inlines = this.Tx1.Inlines;
        inlines.Clear();

        foreach (char ch in this.Tb1.Text)
        {
            if (Char.IsDigit(ch))
            {
                var run = new Run(ch.ToString());
                run.Foreground = Brushes.Blue;
                inlines.Add(run);
            }
            else if (Char.IsLetter(ch))
            {
                var run = new Run(ch.ToString());
                run.Foreground = Brushes.Red;
                inlines.Add(run);
            }
            else
            {
                var run = new Run(ch.ToString());
                run.Foreground = Brushes.LimeGreen;
                inlines.Add(run);
            }
        }
    }

The trick is using a transparent TextBox over a TextBlock, which can be colored by collecting many different Run elements.