RichTextBox中文本的动态样式子字符串
本文关键字:样式 字符串 动态 中文 文本 RichTextBox | 更新日期: 2023-09-27 18:13:28
那么,我有一个WPF RichTextBox
,它将被绑定到一长行文本。
我想做的是使用一组两个TextPointer
对象,这样在任何给定的时间,两个指针之间的文本都有一个应用于它的样式。(例如,在用户移动选择时更改文本的背景/前景色)。一旦文本不再位于两个指针之间,样式必须重置为原始样式。
期望的行为类似(虽然不相同)的方式,你可以点击和拖动,以突出显示/选择网站上的文本,例如。而不是点击和拖动(用户不应该能够这样做,我将通过编程确定端点。)
我似乎想不出一个方法来做这件事。我知道我可以将所需的样式应用于<Run></Run>
,但我不知道如何从控件内获得文本的某一子字符串,并以编程方式应用(以及删除)Run
标签。
理想的解决方案是更改select方法所应用的样式。我对这样做有点警惕(如果它甚至可以做到),因为我不确定是否有可能禁用用户的选择(不禁用鼠标),并且仍然有编程选择可供我使用。
更新:我想你最初谈论的是TextBlock
,而不是RichTextBox
。如果解决方案绝对需要RichTextBox
,则需要在某处寻找可用的RTF解析器。
或者,您可以使用下面的代码,这是我拿枪指着我的头写的(实际上,我写它是为了看看我能不能)。这可以说是对MVVM的一种罪恶,但是您可以闭上眼睛,假装<Bold>
等标记只是一些任意的标记语言,而不是XAML。
anyway:当需要格式化的范围发生变化时,更新FormattedText
属性并引发PropertyChanged
。
namespace HollowEarth.AttachedProperties
{
public static class TextProperties
{
#region TextProperties.XAMLText Attached Property
public static String GetXAMLText(TextBlock obj)
{
return (String)obj.GetValue(XAMLTextProperty);
}
public static void SetXAMLText(TextBlock obj, String value)
{
obj.SetValue(XAMLTextProperty, value);
}
/// <summary>
/// Convert raw string into formatted text in a TextBlock:
///
/// @"This <Bold>is a test <Italic>of the</Italic></Bold> text."
///
/// Text will be parsed as XAML TextBlock content.
///
/// See WPF TextBlock documentation for full formatting. It supports spans and all kinds of things.
///
/// </summary>
public static readonly DependencyProperty XAMLTextProperty =
DependencyProperty.RegisterAttached("XAMLText", typeof(String), typeof(TextProperties),
new PropertyMetadata("", XAMLText_PropertyChanged));
// I don't recall why this was necessary; maybe it wasn't.
public static Stream GetStream(String s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
private static void XAMLText_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBlock)
{
var ctl = d as TextBlock;
try
{
// XAML needs a containing tag with a default namespace. We're parsing
// TextBlock content, so make the parent a TextBlock to keep the schema happy.
// TODO: If you want any content not in the default schema, you're out of luck.
var strText = String.Format(@"<TextBlock xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">{0}</TextBlock>", e.NewValue);
TextBlock parsedContent = System.Windows.Markup.XamlReader.Load(GetStream(strText)) as TextBlock;
// The Inlines collection contains the structured XAML content of a TextBlock
ctl.Inlines.Clear();
// UI elements are removed from the source collection when the new parent
// acquires them, so pass in a copy of the collection to iterate over.
ctl.Inlines.AddRange(parsedContent.Inlines.ToList());
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(String.Format("Error in HollowEarth.AttachedProperties.TextProperties.XAMLText_PropertyChanged: {0}", ex.Message));
throw;
}
}
}
#endregion TextProperties.XAMLText Attached Property
}
}
其他c# // This `SpanStyle` resource is in scope for the `TextBlock` I attached
// the property to. This works for me with a number of properties, but
// it's not changing the foreground. If I apply the same style conventionally
// to a Span in the real XAML, the foreground color is set. Very curious.
// StaticResource threw an exception for me. I couldn't figure out what to give
// XamlReader.Load for a ParserContext.
FormattedText = "Text <Span Style='"{DynamicResource SpanStyle}'">Span Text</Span>";
XAML
<TextBlock
xmlns:heap="clr-namespace:HollowEarth.AttachedProperties"
heap:TextProperties.XAMLText="{Binding FormattedText}"
/>
<TextBlock
xmlns:heap="clr-namespace:HollowEarth.AttachedProperties"
heap:TextProperties.XAMLText="This is <Italic Foreground="Red">italic and <Bold>bolded</Bold></Italic> text"
/>