【问题标题】:XAML Convert textblock text to InlinesXAML 将文本块文本转换为内联
【发布时间】:2016-03-09 18:57:16
【问题描述】:

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

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

但设置为文本值不考虑&lt;Bold&gt;标签。

所以我搜索了如何做,唯一的答案是“创建内联并将其添加到您的 textBlock”。 但我不想在我的视图模型上这样做。

所以我正在寻找一个转换器来用内联集合替换我的文本属性,以在我的 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)。

我试过这个但我有一个错误(无法将绑定转换为字符串):

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

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

【问题讨论】:

    标签: c# xaml windows-10 uwp


    【解决方案1】:

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

    创建一个格式化程序类:

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

    【讨论】:

    • 很高兴您能够修改代码以使用 UWP!
    • 对这个问题的扩展:“变量”是如何传递给这个的?我可以看到使用的是 FormattedText 而不是 Text,但是如果要“加粗”特定单词,那么如何在 xaml 中传递该单词?
    【解决方案2】:

    我一直在为 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}" />
    

    【讨论】:

    • 这是个好主意,但在 UWP 项目中找不到“FrameworkPropertyMetadata”
    【解决方案3】:

    我使用这样的东西:

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

    输出将是:

    粗体文本在同一个 TextBlock 上添加具有不同 FontWeigth 的新文本

    【讨论】:

      【解决方案4】:

      我希望我的贡献仍然有用,或者可能对其他解决此问题的人有用。我已经从@Geoffrey 更新了 Formatter 类,所以textblock 中的特定字符是turning 粗体。我在顶部有一个人员列表和一个搜索查询。人名中的查询部分变为粗体

      查询:ic
      结果:Rick

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

      在 XAML 中使用:

      <TextBlock Text="{Binding Name}" helpers:TextBlockFormatter.FormattedText="{Binding ElementName=queryTextBox, Path=Text}"  />
      

      我遇到了一些问题,例如我的datasource 在调用FormattedTextPropertyChanged 时没有设置。您还需要注意转义文本。我使用Replace 函数让自己变得轻松。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-18
        相关资源
        最近更新 更多