[英]XAML Convert textblock text to Inlines
I want to set this kind of text on TextBlock in a UWP project : 我想在UWP项目中的TextBlock上设置这种文本:
"<Bold>" + variable + "</Bold>"
But set it to Text value do not consider <Bold>
tags. 但是将其设置为Text值不要考虑<Bold>
标签。
So i searched how to do and the only one answer is "creat Inlines and add it to your textBlock". 所以我搜索了如何做,唯一的答案是“创建内联并将其添加到您的textBlock”。 but i don't want to do it on my View Model. 但我不想在我的视图模型上这样做。
So i'm looking for a converter to replace my text attribute by a inlines collection to set on my textBlock. 所以我正在寻找一个转换器来替换我的text属性,通过inline集合来设置我的textBlock。 I found some example ( 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 ), but not working on universal Windows apps (UWP). 我找到了一些例子( 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)。
I tried this but i have an error (unable to cast Binding to string): 我试过这个,但我有一个错误(无法将Binding强制转换为字符串):
<TextBlock x:Name="newsArticleSections"
Tag="{Binding RelativeSource={RelativeSource Self}, Mode=OneWay, Converter={StaticResource TextToRunConverter}, ConverterParameter={Binding ArticleSections}}"/>
And this is my converter : 这是我的转换器:
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;
}
It's just the ways that i had explored, but with no result for the moment. 这只是我探索的方式,但暂时没有结果。 Does someone has another idea ? 有人有另一个想法吗?
I've been using the following solution for WPF projects (not UWP), so I'm not sure if it will work for you, but feel free to give it a try. 我一直在使用以下WPF项目的解决方案(不是UWP),所以我不确定它是否适合你,但请随意尝试一下。
You begin by putting the following into a class file within, say, a Helpers folder inside your project: 首先,将以下内容放入项目中的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);
}
}
}
Then, in your XAML file, reference the namespace, like so: 然后,在您的XAML文件中,引用命名空间,如下所示:
xmlns:helpers="clr-namespace:MyProject.Helpers"
To use the formatter, simply add a TextBlock
and declare your binding on FormattedText
(instead of Text
), like this: 要使用格式化程序,只需添加一个TextBlock
并在FormattedText
(而不是Text
)上声明您的绑定,如下所示:
<TextBlock helpers:Formatter.FormattedText="{Binding Content}" />
@devuxer answer was a good idea, but only for WPF project. @devuxer回答是一个好主意,但仅适用于WPF项目。 So i used it to make UWP solution and it works : 所以我用它来制作UWP解决方案并且它有效:
Create a Formatter class : 创建一个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);
}
}
And add this reference to your XAML file : 并将此引用添加到您的XAML文件:
xmlns:helpers="using:MyProject.Helpers"
To use the formatter, simply add a TextBlock and declare your binding on FormattedText, like this : 要使用格式化程序,只需添加一个TextBlock并在FormattedText上声明您的绑定,如下所示:
<TextBlock x:Name="textBlock" helpers:TextBlockFormatter.FormattedText="{Binding Content}">
I use something like this: 我使用这样的东西:
XAML XAML
<TextBlock Name="TB" Text="Bold Text " FontWeight="Bold" />
At the Controller: 在控制器:
TB.Inlines.Add(new Run { Text = "New append text with diferent FontWeigth on the same TextBlock", FontWeight = FontWeights.Normal } );
Output will be: 输出将是:
Bold Text New append text with diferent FontWeigth on the same TextBlock 粗体文本在同一TextBlock上添加不同FontWeigth的新文本
I hope my contribution is still useful, or may be useful to other reaching this question. 我希望我的贡献仍然有用,或者可能对其他人有用。 I've updated the Formatter class from @Geoffrey, so that specific characters in the textblock
are tur nin g bold. 我已经更新从@Geoffrey Formatter类,所以在那个特定的字符textblock
是TUR 万年摹大胆。 I having a list with people and a search query at the top. 我有一个人员列表和顶部的搜索查询。 The query part in name of the person is turning bold . 该人名称中的查询部分变为粗体 。
Query: ic 查询:ic
Result: R ic k 结果:R ic k
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("&", "&");
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("&", "&");
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("&", "&");
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);
}
}
Use in XAML: 在XAML中使用:
<TextBlock Text="{Binding Name}" helpers:TextBlockFormatter.FormattedText="{Binding ElementName=queryTextBox, Path=Text}" />
I had some issues, For example my datasource
was not set when the FormattedTextPropertyChanged
was called. 我有一些问题,例如,在调用FormattedTextPropertyChanged
时,我的datasource
未设置。 Also you need to take care of escaping the text. 您还需要注意转义文本。 I made myself easy by using the Replace
function. 通过使用Replace
功能,我轻松自如。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.