Search code examples
c#windows-phone-8windows-store-appswindows-phone-8.1

Text formatting in TextBlock Windows Phone 8.1


I have a list of strings in my ViewModel with the following format:

 This is an <b>example.<b>

I want to have some kind of text control in my view that will display the formatted text via DataBinding*, like this:

This is an example.

I don't find any built-in control that can behave like this.

Does anyone know how to deal with it?


Solution

  • You can use Run:

    <TextBlock FontSize="30">
        <Run>This is an</Run>
        <Run FontWeight="Bold" Text=" example"/>
    </TextBlock>
    

    For this you will have to parse your strings, select bold sections, and define content in the code behind. A very simple example can look like this:

    string example = @"This is an <b>example.</b>";
    var str = example.Split(new string[] { "<b>", "</b>" }, StringSplitOptions.None);
    for (int i = 0; i < str.Length; i++)
        myTextBlock.Inlines.Add(new Run { Text = str[i], FontWeight = i % 2 == 1 ? FontWeights.Bold : FontWeights.Normal });
    

    Edit - using with Binding

    If you want to use the above procedure with Binding, then it's not so simple - TextBlock.Inlines is not a DependencyProperty, so we cannot use it. Nevertheless there is a way to do it - you need to extend somehow your TextBlock - here is another pitfall - it's sealed class so no inheritance. In this case we will have to use another class (here is also a good example):

    public static class TextBlockExtension
    {
        public static string GetFormattedText(DependencyObject obj)
        { return (string)obj.GetValue(FormattedTextProperty); }
    
        public static void SetFormattedText(DependencyObject obj, string value)
        { obj.SetValue(FormattedTextProperty, value); }
    
        public static readonly DependencyProperty FormattedTextProperty =
            DependencyProperty.Register("FormattedText", typeof(string), typeof(TextBlockExtension),
            new PropertyMetadata(string.Empty, (sender, e) =>
            {
                string text = e.NewValue as string;
                var textBl = sender as TextBlock;
                if (textBl != null)
                {
                    textBl.Inlines.Clear();
                    var str = text.Split(new string[] { "<b>", "</b>" }, StringSplitOptions.None);
                    for (int i = 0; i < str.Length; i++)
                        textBl.Inlines.Add(new Run { Text = str[i], FontWeight = i % 2 == 1 ? FontWeights.Bold : FontWeights.Normal });
                }
            }));
    }
    

    Then you can use it in xaml like this:

    <TextBlock local:TextBlockExtension.FormattedText="{Binding MyText}"/>