所以,我有一个WPF RichTextBox
,它将绑定一长串文本。
我想要做的是使用一组两个TextPointer
对象,以便在任何给定时间,两个指针之间的文本都应用了一个样式。 (例如,在用户移动选择时更改文本的背景/前景色。)一旦文本不再在两个指针之间,样式必须重置为原始样式。
例如,您可以单击并拖动以突出显示/选择网站上的文本的方式与所需行为类似(但不相同)。而不是单击和拖动(用户不应该这样做,我将以编程方式确定端点。)
我似乎无法找到办法。我知道我可以将所需的样式应用于<Run></Run>
,但我无法弄清楚如何从控件中获取文本的某个子字符串并应用(以及删除)Run
以编程方式标记它。
理想的解决方案是更改select方法应用的样式。我有点担心这样做(如果它甚至可以完成)因为我不确定是否可以禁用用户的选择(不禁用鼠标)并且仍然可以使用程序选择。
答案 0 :(得分:1)
更新:我认为您最初谈论的是TextBlock
,而不是RichTextBox
。如果解决方案绝对需要RichTextBox
,那么您需要研究在某处找到可用的RTF解析器。
您可以做的一件事是使用RTF或HTML控件。
或者,你可以使用下面的代码,我用枪写到我的头上(实际上,我写了它,看看我是否可以)。它可以说是对MVVM的一种罪恶,但你可以闭上眼睛,假装<Bold>
等标签只是一些任意的标记语言,而不是XAML。
无论如何:当要格式化的所需范围发生变化时,请更新FormattedText
属性并引发PropertyChanged
。
C#
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"
/>