XAML将文本块文本转换为内联

时间:2015-12-04 18:35:23

标签: c# xaml windows-10 uwp

我想在UWP项目中的TextBlock上设置这种文本:

"<Bold>" + variable + "</Bold>"

但是将其设置为文本值不考虑<Bold>标记。

所以我搜索了怎么做,唯一的答案是&#34;创建内联并将其添加到textBlock&#34;。 但我不想在我的View Model上做这件事。

所以我正在寻找一个转换器,用inline集合替换我的text属性,以便在我的textBlock上设置。 我找到了一些示例(https://social.msdn.microsoft.com/Forums/en-US/1a1af975-e186-4167-b1c9-cc86afcdd93a/how-to-show-text-in-textblock-as-rich-text-format?forum=wpf),但没有使用通用Windows应用程序(UWP)。

我试过这个但是我有一个错误(无法将Binding强制转换为字符串):

<TextBlock  x:Name="newsArticleSections"
                            Tag="{Binding RelativeSource={RelativeSource Self}, Mode=OneWay, Converter={StaticResource TextToRunConverter}, ConverterParameter={Binding ArticleSections}}"/>

这是我的转换器:

public object Convert(object value, Type targetType, object parameter, string language)
    {
        TextBlock textblock = value as TextBlock;

        textblock.ClearValue(TextBlock.TextProperty);
        Run run = new Run();
        run.Text = (string)parameter;
        textblock.Inlines.Add(run);
        return null;
    }

这只是我探索的方式,但暂时没有结果。 有人有另一个想法吗?

4 个答案:

答案 0 :(得分:3)

我一直在为WPF项目使用以下解决方案(不是UWP),所以我不确定它是否适合您,但请随意尝试。

首先将以下内容放入项目中的Helpers文件夹中的类文件中:

public class Formatter
{
    public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
        "FormattedText",
        typeof(string),
        typeof(Formatter),
        new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsMeasure, FormattedTextPropertyChanged));

    public static void SetFormattedText(DependencyObject textBlock, string value)
    {
        textBlock.SetValue(FormattedTextProperty, value);
    }

    public static string GetFormattedText(DependencyObject textBlock)
    {
        return (string)textBlock.GetValue(FormattedTextProperty);
    }

    private static void FormattedTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBlock = d as TextBlock;
        if (textBlock == null) return;
        const string @namespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
        var formattedText = (string)e.NewValue ?? string.Empty;
        formattedText = $@"<Span xml:space=""preserve"" xmlns=""{@namespace}"">{formattedText}</Span>";

        textBlock.Inlines.Clear();
        using (var xmlReader = XmlReader.Create(new StringReader(formattedText)))
        {
            var result = (Span)XamlReader.Load(xmlReader);
            textBlock.Inlines.Add(result);
        }
    }
}

然后,在您的XAML文件中,引用名称空间,如下所示:

xmlns:helpers="clr-namespace:MyProject.Helpers"

要使用格式化板,只需添加TextBlock并在FormattedText(而非Text)上声明您的绑定,如下所示:

<TextBlock helpers:Formatter.FormattedText="{Binding Content}" />

答案 1 :(得分:3)

@devuxer回答是一个好主意,但仅适用于WPF项目。 所以我用它来制作UWP解决方案并且它有效:

创建一个Formatter类:

public class TextBlockFormatter
{
    public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
    "FormattedText",
    typeof(string),
    typeof(TextBlockFormatter),
    new PropertyMetadata(null, FormattedTextPropertyChanged));

    public static void SetFormattedText(DependencyObject textBlock, string value)
    {
        textBlock.SetValue(FormattedTextProperty, value);
    }

    public static string GetFormattedText(DependencyObject textBlock)
    {
        return (string)textBlock.GetValue(FormattedTextProperty);
    }

    private static void FormattedTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // Clear current textBlock
        TextBlock textBlock = d as TextBlock;
        textBlock.ClearValue(TextBlock.TextProperty);
        textBlock.Inlines.Clear();
        // Create new formatted text
        string formattedText = (string)e.NewValue ?? string.Empty;
        string @namespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
        formattedText = $@"<Span xml:space=""preserve"" xmlns=""{@namespace}"">{formattedText}</Span>";
        // Inject to inlines
        var result = (Span)XamlReader.Load(formattedText);
        textBlock.Inlines.Add(result);
    }

}

并将此引用添加到您的XAML文件中:

xmlns:helpers="using:MyProject.Helpers"

要使用格式化程序,只需添加一个TextBlock并在FormattedText上声明您的绑定,如下所示:

<TextBlock  x:Name="textBlock" helpers:TextBlockFormatter.FormattedText="{Binding Content}">

答案 2 :(得分:1)

我使用这样的东西:

XAML

<TextBlock Name="TB" Text="Bold Text " FontWeight="Bold"  />

在控制器:

TB.Inlines.Add(new Run { Text = "New append text with diferent FontWeigth on the same TextBlock", FontWeight = FontWeights.Normal } );

输出将是:

粗体文字在同一文字框上使用不同FontWeigth的新附加文字

答案 3 :(得分:0)

我希望我的贡献仍然有用,或者对其他人来说可能有用。我已经从@Geoffrey更新了Formatter类,因此 public void mouseDragged(MouseEvent event) { int x2 =event.getX(); int y2=event.getY(); mouseMoved(event); canvas.repaint(); } } 中的特定字符是tur nin g bold。我有一个人员列表和顶部的搜索查询。此人的姓名中的查询部分正在变为粗体

查询:ic
结果:R ic k

textblock

在XAML中使用:

public class TextBlockFormatter
{
    const string @namespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";

    public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
    "FormattedText",
    typeof(string),
    typeof(TextBlockFormatter),
    new PropertyMetadata(null, FormattedTextPropertyChanged));

    public static void SetFormattedText(DependencyObject textBlock, string value)
    {
        textBlock.SetValue(FormattedTextProperty, value);
    }

    public static string GetFormattedText(DependencyObject textBlock)
    {
        return (string)textBlock.GetValue(FormattedTextProperty);
    }

    private static void FormattedTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBlock = (TextBlock)d;
        if (textBlock.DataContext == null)
        {
            textBlock.DataContextChanged += TextBlock_DataContextChanged;
            return;
        }

        var query = (string)e.NewValue ?? string.Empty;
        HighlightSearch(textBlock, query);
    }

    private static void HighlightSearch(TextBlock textBlock, string value)
    {
        var name = ((Person)textBlock.DataContext).Name;
        var query = value.ToUpper();

        var indexOfSearch = name.ToUpper().IndexOf(query, 0);

        if (indexOfSearch < 0) return;

        // add normal text first
        var firstText = name.Substring(0, indexOfSearch).Replace("&", "&amp;");
        var first = $@"<Span xml:space=""preserve"" xmlns=""{@namespace}"">{firstText}</Span>";
        var firstResult = (Span)XamlReader.Load(first);

        // add the bold text
        var boldText = name.Substring(indexOfSearch, query.Length).Replace("&", "&amp;");
        var bold = $@"<Bold xml:space=""preserve"" xmlns=""{@namespace}"">{boldText}</Bold>";
        var boldResult = (Bold)XamlReader.Load(bold);

        // add the rest of the text
        var restStartIndex = indexOfSearch + query.Length;
        var restText = name.Substring(restStartIndex, name.Length - restStartIndex).Replace("&", "&amp;");
        var rest = $@"<Span xml:space=""preserve"" xmlns=""{@namespace}"">{restText}</Span>";
        var restResult = (Span)XamlReader.Load(rest);

        // Clear current textBlock
        textBlock.ClearValue(TextBlock.TextProperty);
        textBlock.Inlines.Clear();

        // Inject to inlines
        textBlock.Inlines.Add(firstResult);
        textBlock.Inlines.Add(boldResult);
        textBlock.Inlines.Add(restResult);
    }

    private static void TextBlock_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
    {
        var block = (TextBlock)sender;

        if (block.DataContext == null) return;

        block.DataContextChanged -= TextBlock_DataContextChanged;

        var query = (string)sender.GetValue(FormattedTextProperty);
        HighlightSearch(block, query);
    }
}

我遇到了一些问题,例如调用<TextBlock Text="{Binding Name}" helpers:TextBlockFormatter.FormattedText="{Binding ElementName=queryTextBox, Path=Text}" /> 后我的datasource未设置。您还需要处理转义文本。我使用FormattedTextPropertyChanged函数轻松自如。