Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
753 views
in Technique[技术] by (71.8m points)

wpf - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...