Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Format part of the text of TextBlock using iValueConverter

I want to make part of the text of a textblock bold. This is what i tried in the IValueConverter but it does not seem to work.

public class Highlighter : IValueConverter
    {


        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
            {
                return null;
            }

            return "Question1:<Bold>Answer1</Bold>, Question2:<Bold>Answer2</Bold>, Question3:<Bold>Answer3</Bold>";

        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

This does not make the Answer bold.

This is how i am using it in XAML.

<TextBlock Height="Auto" Width="Auto" MaxHeight="64" Text="{Binding Path=QuestionAnswer, Mode=OneWay, Converter={x:Static Highlighter}}" />

Is there a way i can achieve this by formatting the text or by sending the TextBlock to the converter?

like image 772
Asdfg Avatar asked Dec 27 '12 17:12

Asdfg


2 Answers

It is definitely possible to do with TextBlock control, but considering all the efforts you might want to switch to other control (ItemsControl for example).

Anyway, here is a solution. There are actually several problems to solve:

  1. TextBlock.Text property is string, and you can't assign preformatted text to it
  2. TextBlock.Inlines can accept formatted text, but it is read-only property
  3. You'll have to format text yourself (probably there are easy ways to parse text with tags and produce formatted output as a collection of Inline objects, but I don't know any)

You can create an attached property to deal with the first 2 problems:

public static class TextBlockEx
{
    public static Inline GetFormattedText(DependencyObject obj)
    {
        return (Inline)obj.GetValue(FormattedTextProperty);
    }

    public static void SetFormattedText(DependencyObject obj, Inline value)
    {
        obj.SetValue(FormattedTextProperty, value);
    }

    public static readonly DependencyProperty FormattedTextProperty =
        DependencyProperty.RegisterAttached(
            "FormattedText",
            typeof(Inline),
            typeof(TextBlockEx),
            new PropertyMetadata(null, OnFormattedTextChanged));

    private static void OnFormattedTextChanged(
        DependencyObject o,
        DependencyPropertyChangedEventArgs e)
    {
        var textBlock = o as TextBlock;
        if(textBlock == null) return;

        var inline = (Inline)e.NewValue;
        textBlock.Inlines.Clear();
        if(inline != null)
        {
            textBlock.Inlines.Add(inline);
        }
    }
}

XAML would change just a bit:

<TextBlock local:TextBlockEx.FormattedText="{Binding Path=QuestionAnswer,
                                                     Mode=OneWay,
                                                     Converter={x:Static Highlighter}}" />

Note that you'll need to map you namespace where TextBlockEx is declared in xmlns:local="clr-namepace:<namespace_name>" in XAML.

Now you need to construct formatted text in converter instead of plain text to solve the last problem:

public object Convert(object value, Type targetType, object parameter,
    CultureInfo culture)
{
    if(value == null)
    {
        return null;
    }

    var span = new Span();
    span.Inlines.Add(new Run("Question1: "));
    span.Inlines.Add(new Run("Answer1") { FontWeight = FontWeights.Bold });
    span.Inlines.Add(new Run(", "));

    span.Inlines.Add(new Run("Question2: "));
    span.Inlines.Add(new Run("Answer2") { FontWeight = FontWeights.Bold });
    span.Inlines.Add(new Run(", "));

    span.Inlines.Add(new Run("Question3: "));
    span.Inlines.Add(new Run("Answer3") { FontWeight = FontWeights.Bold });

    return span;
}
like image 106
max Avatar answered Oct 22 '22 08:10

max


Ya, something like this should put ya on track;

<TextBlock>
   <Run Text="Question / Binding / Whatever..."/>
   <Run Text="Answer / Binding / Whatever..." FontWeight="Bold"/>
</TextBlock>
like image 45
Chris W. Avatar answered Oct 22 '22 07:10

Chris W.