使用iValueConverter格式化TextBlock文本的一部分

问题描述 投票:5回答:2

我想将文本块的一部分粗体化。这是我在IValueConverter中尝试但它似乎不起作用。

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

这不会使答案变得大胆。

这就是我在XAML中使用它的方式。

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

有没有办法通过格式化文本或将TextBlock发送到转换器来实现这一目标?

wpf ivalueconverter
2个回答
13
投票

绝对有可能与TextBlock控制,但考虑到你可能想要切换到其他控件(例如ItemsControl)的所有努力。

无论如何,这是一个解决方案。实际上有几个问题需要解决:

  1. TextBlock.Text属性是string,您不能为其分配预先格式化的文本
  2. TextBlock.Inlines可以接受格式化文本,但它是只读属性
  3. 你必须自己格式化文本(可能有简单的方法用标签解析文本并生成格式化的输出作为Inline对象的集合,但我不知道任何)

您可以创建附加属性来处理前两个问题:

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会稍微改变一下:

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

请注意,您需要映射名称空间,其中TextBlockEx在XAML中的xmlns:local="clr-namepace:<namespace_name>"中声明。

现在你需要在转换器而不是纯文本中构造格式化文本来解决最后一个问题:

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

2
投票

雅,这样的事情应该让你走上正轨;

<TextBlock>
   <Run Text="Question / Binding / Whatever..."/>
   <Run Text="Answer / Binding / Whatever..." FontWeight="Bold"/>
</TextBlock>
© www.soinside.com 2019 - 2024. All rights reserved.