Search code examples
c#textboxwindows-store-appswinrt-xamltext-coloring

Selective coloring of the text in TextBox (Windows Store App)


Code in my MainPage.xaml

<TextBox x:Name="TextTextBox" 
          Text="{Binding Path=Text, Mode=TwoWay}"
          TextWrapping="Wrap" />

.
.
.

<!--Button with some Command-->
<Button x:Name="SearchButton" 
                    Content="Search" 
                    HorizontalAlignment="Center"
                    Command="{Binding Command}"/>

Code in my ViewModel (property that is binded with TextBox)

public string Text
{
    get
    {
        return ssModel.Text;
    }
    set
    {
        ssModel.Text = value;
        OnPropertyChanged();
    }
}

When you press SearchButton, is performing Command which return List of ints (this ints are indexes to coloring in TextBox).

For example I've Text:

LoremIpsumDolorSitAmet

Then I press SearchButton, Command return me for example list of three numbers {2, 5, 13}. Now I want to coloring TextTextBox characters on this positions so, I want to get something like:

Result what I want

And this is exactly what I want to get. Coloring text in TextTextBox on the specified possitions.

I change TextBox to RichEditBox and write DependencyProperty to bind control with property in View Model. This is class with DependencyProperty:

public class RichTextC : DependencyObject
 {
    public static string GetRichText(DependencyObject obj)
    {
        return (string)obj.GetValue(RichTextProperty);
    }

    public static void SetRichText(DependencyObject obj, string value)
    {
        obj.SetValue(RichTextProperty, value);
    }

    public static readonly DependencyProperty RichTextProperty =
        DependencyProperty.Register("RichText", typeof(string), typeof(RichTextC), new PropertyMetadata(string.Empty, callback));

    private static void callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var reb = (RichEditBox)d;
        reb.Document.SetText(TextSetOptions.FormatRtf, (string)e.NewValue);
    }
 }

And RichEditBox at MainPage.xaml:

<RichEditBox local:RichTextC.RichText="{Binding MyRichText, Mode=TwoWay}" 
                     Margin="0,30,0,0""/>

But I have a another problem, because this DependencyProperty bind only in one way. When I set text/content of property at View Model control RichEditBox at MainPage will be notify and show new text. But when I change content of RichEditBox at MainPage it does not notify property in View Model - so binding from View to View Model does not work.


Solution

  • The TextBox doesn't support multi-coloured text. If you want editable coloured text you'll need to use the RichEditBox instead.

    However, there isn't a direct way to bind to the text of a RichEditBox. You can set the text and its character formatting programatically through the RichEditBox's ITextDocument interfaces. For example, the following will set position 2 to Red. You can loop through your list of ints to set all of its ranges before calling ApplyDisplayUpdates:

    ITextDocument doc = rtb.Document;
    ITextRange range = doc.GetRange(2,3);
    range.CharacterFormat.ForegroundColor = Windows.UI.Colors.Red;
    rtb.Document.ApplyDisplayUpdates();
    

    The other possibility would be to create a string with RTF codes in it and set that with ITextDocument.SetText.

    If you want to bind the Text you can create an attached property which accepts the RTF and calls SetText or which accepts your own simpler mark-up script and calls ITextRange.CharacterFormat.ForegroundColor. Either way it would be similar to what I demonstrated to bind HTML to a WebView in my blog entry Binding HTML to a WebView with Attached Properties