RichTextBox中文本的动态样式子字符串

本文关键字:样式 字符串 动态 中文 文本 RichTextBox | 更新日期: 2023-09-27 18:13:28

那么,我有一个WPF RichTextBox,它将被绑定到一长行文本。

我想做的是使用一组两个TextPointer对象,这样在任何给定的时间,两个指针之间的文本都有一个应用于它的样式。(例如,在用户移动选择时更改文本的背景/前景色)。一旦文本不再位于两个指针之间,样式必须重置为原始样式。

期望的行为类似(虽然不相同)的方式,你可以点击和拖动,以突出显示/选择网站上的文本,例如。而不是点击和拖动(用户不应该能够这样做,我将通过编程确定端点。)

我似乎想不出一个方法来做这件事。我知道我可以将所需的样式应用于<Run></Run>,但我不知道如何从控件内获得文本的某一子字符串,并以编程方式应用(以及删除)Run标签。

理想的解决方案是更改select方法所应用的样式。我对这样做有点警惕(如果它甚至可以做到),因为我不确定是否有可能禁用用户的选择(不禁用鼠标),并且仍然有编程选择可供我使用。

RichTextBox中文本的动态样式子字符串

更新:我想你最初谈论的是TextBlock,而不是RichTextBox。如果解决方案绝对需要RichTextBox,则需要在某处寻找可用的RTF解析器。

你可以做的一件事是使用RTF或HTML控件。

或者,您可以使用下面的代码,这是我拿枪指着我的头写的(实际上,我写它是为了看看我能不能)。这可以说是对MVVM的一种罪恶,但是您可以闭上眼睛,假装<Bold>等标记只是一些任意的标记语言,而不是XAML。

anyway:当需要格式化的范围发生变化时,更新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 &lt;Italic Foreground=&quot;Red&quot;&gt;italic and &lt;Bold&gt;bolded&lt;/Bold&gt;&lt;/Italic&gt; text"
        />