【问题标题】:Richtextbox wpf bindingRichtextbox wpf 绑定
【发布时间】:2010-09-25 12:01:35
【问题描述】:

要在 WPF RichtextBox 中对 Document 进行 DataBinding,到目前为止,我看到了 2 个解决方案,它们是从 RichtextBox 派生并添加 DependencyProperty,以及带有“代理”的解决方案.

第一个或第二个都不令人满意。有人知道另一种解决方案,或者是能够DataBinding 的商业RTF 控件吗?普通的TextBox 不是替代品,因为我们需要文本格式。

有什么想法吗?

【问题讨论】:

    标签: c# wpf data-binding richtextbox


    【解决方案1】:

    创建一个包含名为 RTB 的 RichTextBox 的 UserControl。现在添加以下依赖属性:

        public FlowDocument Document
        {
            get { return (FlowDocument)GetValue(DocumentProperty); }
            set { SetValue(DocumentProperty, value); }
        }
    
        public static readonly DependencyProperty DocumentProperty =
            DependencyProperty.Register("Document", typeof(FlowDocument), typeof(RichTextBoxControl), new PropertyMetadata(OnDocumentChanged));
    
        private static void OnDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RichTextBoxControl control = (RichTextBoxControl) d;
            FlowDocument document = e.NewValue as FlowDocument;
            if (document  == null)
            {
                control.RTB.Document = new FlowDocument(); //Document is not amused by null :)
            }
            else
            {
                control.RTB.Document = document;
            }
        }
    

    此解决方案可能是您在某处看到的“代理”解决方案..但是.. RichTextBox 根本没有 Document as DependencyProperty...所以您必须以另一种方式执行此操作...

    HTH

    【讨论】:

    • 在最后一行中,您使用“document”,这会在我的代码中引发错误。由于静态方法,它必须是 Document 的实例。但是什么实例?我正在设置通过 DependencyProperty 获得的文档,即“文档”。删除“静态”会破坏 DependencyProperty 的最后一个参数。所以我在这里卡住了。上面的 Helper 类也不显示任何文本 :(
    【解决方案2】:

    我可以给你一个好的解决方案,你可以接受它,但在我这样做之前,我将尝试解释为什么 Document 不是首先是 DependencyProperty

    RichTextBox 控件的生命周期内,Document 属性通常不会改变。 RichTextBoxFlowDocument 初始化。该文档已显示,可以通过多种方式进行编辑和修改,但Document 属性的基础值仍然是FlowDocument 的一个实例。因此,它确实没有理由应该是DependencyProperty,即Bindable。如果您有多个位置引用此 FlowDocument,则只需引用一次。由于它在任何地方都是相同的实例,因此每个人都可以访问更改。

    我不认为FlowDocument 支持文档更改通知,虽然我不确定。

    话虽如此,这里有一个解决方案。在开始之前,由于RichTextBox 没有实现INotifyPropertyChanged 并且Document 不是DependencyProperty,所以当RichTextBox 的Document 属性发生变化时我们没有通知,因此绑定只能是OneWay。

    创建一个将提供FlowDocument 的类。绑定需要DependencyProperty的存在,所以这个类继承自DependencyObject

    class HasDocument : DependencyObject
    {
        public static readonly DependencyProperty DocumentProperty =
            DependencyProperty.Register("Document", 
                                        typeof(FlowDocument), 
                                        typeof(HasDocument), 
                                        new PropertyMetadata(new PropertyChangedCallback(DocumentChanged)));
    
        private static void DocumentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            Debug.WriteLine("Document has changed");
        }
    
        public FlowDocument Document
        {
            get { return GetValue(DocumentProperty) as FlowDocument; }
            set { SetValue(DocumentProperty, value); }
        }
    }
    

    使用 XAML 中的富文本框创建 Window

    <Window x:Class="samples.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Flow Document Binding" Height="300" Width="300"
        >
        <Grid>
          <RichTextBox Name="richTextBox" />
        </Grid>
    </Window>
    

    Window 一个HasDocument 类型的字段。

    HasDocument hasDocument;
    

    窗口构造函数应该创建绑定。

    hasDocument = new HasDocument();
    
    InitializeComponent();
    
    Binding b = new Binding("Document");
    b.Source = richTextBox;
    b.Mode = BindingMode.OneWay;
    BindingOperations.SetBinding(hasDocument, HasDocument.DocumentProperty, b);
    

    如果您希望能够在 XAML 中声明绑定,则必须使您的 HasDocument 类派生自 FrameworkElement,以便可以将其插入到逻辑树中。

    现在,如果您要更改 HasDocument 上的 Document 属性,富文本框的 Document 也会更改。

    FlowDocument d = new FlowDocument();
    Paragraph g = new Paragraph();
    Run a = new Run();
    a.Text = "I showed this using a binding";
    g.Inlines.Add(a);
    d.Blocks.Add(g);
    
    hasDocument.Document = d;
    

    【讨论】:

    • +1 是一个很好的答案,但有一个小问题:将 Document 属性设置为依赖属性是有原因的——以方便将控件与 MVVM 模式一起使用。
    • 公平点,但我不同意;仅仅因为 MVVM 在 WPF 应用程序中被广泛使用并不意味着 WPF 的 API 应该仅仅为了适应它而改变。我们以任何可能的方式解决它。这是一种解决方案。我们也可以简单地选择将富文本框封装在用户控件中,并在 UserControl 上定义依赖属性。
    【解决方案3】:

    有一个更简单的方法!

    您可以轻松创建附加的DocumentXaml(或DocumentRTF)属性,该属性将允许您绑定RichTextBox 的文档。它是这样使用的,其中Autobiography 是数据模型中的字符串属性:

    <TextBox Text="{Binding FirstName}" />
    <TextBox Text="{Binding LastName}" />
    <RichTextBox local:RichTextBoxHelper.DocumentXaml="{Binding Autobiography}" />
    

    瞧!完全可绑定RichTextBox 数据!

    此属性的实现非常简单:设置属性后,将 XAML(或 RTF)加载到新的 FlowDocument 中。当FlowDocument 发生变化时,更新属性值。

    这段代码应该可以解决问题:

    using System.IO;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    public class RichTextBoxHelper : DependencyObject
    {
        public static string GetDocumentXaml(DependencyObject obj)
        {
            return (string)obj.GetValue(DocumentXamlProperty);
        }
    
        public static void SetDocumentXaml(DependencyObject obj, string value)
        {
            obj.SetValue(DocumentXamlProperty, value);
        }
    
        public static readonly DependencyProperty DocumentXamlProperty =
            DependencyProperty.RegisterAttached(
                "DocumentXaml",
                typeof(string),
                typeof(RichTextBoxHelper),
                new FrameworkPropertyMetadata
                {
                    BindsTwoWayByDefault = true,
                    PropertyChangedCallback = (obj, e) =>
                    {
                        var richTextBox = (RichTextBox)obj;
    
                        // Parse the XAML to a document (or use XamlReader.Parse())
                        var xaml = GetDocumentXaml(richTextBox);
                        var doc = new FlowDocument();
                        var range = new TextRange(doc.ContentStart, doc.ContentEnd);
    
                        range.Load(new MemoryStream(Encoding.UTF8.GetBytes(xaml)),
                              DataFormats.Xaml);
    
                        // Set the document
                        richTextBox.Document = doc;
    
                        // When the document changes update the source
                        range.Changed += (obj2, e2) =>
                        {
                            if (richTextBox.Document == doc)
                            {
                                MemoryStream buffer = new MemoryStream();
                                range.Save(buffer, DataFormats.Xaml);
                                SetDocumentXaml(richTextBox,
                                    Encoding.UTF8.GetString(buffer.ToArray()));
                            }
                        };
                    }
                });
    }
    

    相同的代码可用于 TextFormats.RTF 或 TextFormats.XamlPackage。对于 XamlPackage,您将拥有 byte[] 类型的属性,而不是 string

    与普通 XAML 相比,XamlPackage 格式有几个优点,尤其是能够包含图像等资源,而且它比 RTF 更灵活、更易于使用。

    很难相信这个问题持续了 15 个月,没有人指出简单的方法。

    【讨论】:

    • @Kelly,使用 DataFormats.Rtf,这可以解决多个 Richtextbox 问题。
    • 双向对我不起作用(使用 Rtf)。 range.Changed 事件永远不会被调用。
    • @FabianBigler - 嗨 - 如果有人遇到同样的问题 - 您需要将 xmlns:local 声明添加到您的 xaml 文件中,该声明将指向可用的命名空间
    • 有人能举个例子说明自传的价值吗?
    • @AntonBakulev 谢谢!
    【解决方案4】:

    我已经稍微调整了之前的代码。 首先 range.Changed 对我不起作用。 在我将 range.Changed 更改为 richTextBox.TextChanged 后,事实证明 TextChanged 事件处理程序可以递归调用 SetDocumentXaml,因此我提供了针对它的保护。我还使用了 XamlReader/XamlWriter 而不是 TextRange。

    public class RichTextBoxHelper : DependencyObject
    {
        private static HashSet<Thread> _recursionProtection = new HashSet<Thread>();
    
        public static string GetDocumentXaml(DependencyObject obj)
        {
            return (string)obj.GetValue(DocumentXamlProperty);
        }
    
        public static void SetDocumentXaml(DependencyObject obj, string value)
        {
            _recursionProtection.Add(Thread.CurrentThread);
            obj.SetValue(DocumentXamlProperty, value);
            _recursionProtection.Remove(Thread.CurrentThread);
        }
    
        public static readonly DependencyProperty DocumentXamlProperty = DependencyProperty.RegisterAttached(
            "DocumentXaml", 
            typeof(string), 
            typeof(RichTextBoxHelper), 
            new FrameworkPropertyMetadata(
                "", 
                FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                (obj, e) => {
                    if (_recursionProtection.Contains(Thread.CurrentThread))
                        return;
    
                    var richTextBox = (RichTextBox)obj;
    
                    // Parse the XAML to a document (or use XamlReader.Parse())
    
                    try
                    {
                        var stream = new MemoryStream(Encoding.UTF8.GetBytes(GetDocumentXaml(richTextBox)));
                        var doc = (FlowDocument)XamlReader.Load(stream);
    
                        // Set the document
                        richTextBox.Document = doc;
                    }
                    catch (Exception)
                    {
                        richTextBox.Document = new FlowDocument();
                    }
    
                    // When the document changes update the source
                    richTextBox.TextChanged += (obj2, e2) =>
                    {
                        RichTextBox richTextBox2 = obj2 as RichTextBox;
                        if (richTextBox2 != null)
                        {
                            SetDocumentXaml(richTextBox, XamlWriter.Save(richTextBox2.Document));
                        }
                    };
                }
            )
        );
    }
    

    【讨论】:

    • 谢谢洛洛!我也遇到了原始课程的问题。这为我修好了。节省大量时间!
    • 我发现这个解决方案有一个小问题。如果视图未关闭并在调用之间重新创建,则可以多次设置 TextChanged 的​​挂钩。我正在创建一个视图并通过列表选择加载。为了解决这个问题,我创建了一个更典型的方法来挂钩 TextChanged 事件。然后我只是在钩住它之前解开该方法。这确保它只被钩住一次。不再有内存泄漏(也不再有运行缓慢的代码)。
    • 这是一个不错的工作解决方案,但是,根据我的经验,它不适用于多个控件,请参阅我的 answer
    • 这太好了,谢谢。但是,如果您想以编程方式设置绑定不起作用,我认为是因为设置绑定的线程与通过 XAML 设置的线程不同。所以我不得不添加一个 SetDocumentXamlFirst 方法,它不使用递归保护,只有在你第一次想设置值时才会手动调用。
    • VM 中的支持字符串必须是 xml 格式的 FlowDocument,否则加载将失败。例如:&lt;FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&gt;&lt;Paragraph Foreground="Red"&gt;&lt;Bold&gt;Hello&lt;/Bold&gt;&lt;/Paragraph&gt;&lt;/FlowDocument&gt;
    【解决方案5】:

    这是 Lolo 答案的 VB.Net 版本:

    Public Class RichTextBoxHelper
    Inherits DependencyObject
    
    Private Shared _recursionProtection As New HashSet(Of System.Threading.Thread)()
    
    Public Shared Function GetDocumentXaml(ByVal depObj As DependencyObject) As String
        Return DirectCast(depObj.GetValue(DocumentXamlProperty), String)
    End Function
    
    Public Shared Sub SetDocumentXaml(ByVal depObj As DependencyObject, ByVal value As String)
        _recursionProtection.Add(System.Threading.Thread.CurrentThread)
        depObj.SetValue(DocumentXamlProperty, value)
        _recursionProtection.Remove(System.Threading.Thread.CurrentThread)
    End Sub
    
    Public Shared ReadOnly DocumentXamlProperty As DependencyProperty = DependencyProperty.RegisterAttached("DocumentXaml", GetType(String), GetType(RichTextBoxHelper), New FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender Or FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, Sub(depObj, e)
                                                                                                                                                                                                                                                                                                                        RegisterIt(depObj, e)
                                                                                                                                                                                                                                                                                                                    End Sub))
    
    Private Shared Sub RegisterIt(ByVal depObj As System.Windows.DependencyObject, ByVal e As System.Windows.DependencyPropertyChangedEventArgs)
        If _recursionProtection.Contains(System.Threading.Thread.CurrentThread) Then
            Return
        End If
        Dim rtb As RichTextBox = DirectCast(depObj, RichTextBox)
        Try
            rtb.Document = Markup.XamlReader.Parse(GetDocumentXaml(rtb))
        Catch
            rtb.Document = New FlowDocument()
        End Try
        ' When the document changes update the source
        AddHandler rtb.TextChanged, AddressOf TextChanged
    End Sub
    
    Private Shared Sub TextChanged(ByVal sender As Object, ByVal e As TextChangedEventArgs)
        Dim rtb As RichTextBox = TryCast(sender, RichTextBox)
        If rtb IsNot Nothing Then
            SetDocumentXaml(sender, Markup.XamlWriter.Save(rtb.Document))
        End If
    End Sub
    

    结束类

    【讨论】:

      【解决方案6】:

      这个 VB.Net 版本适用于我的情况。我删除了线程集合信号量,而不是使用 RemoveHandler 和 AddHandler。此外,由于 FlowDocument 一次只能绑定到一个 RichTextBox,因此我检查了 RichTextBox 的 IsLoaded=True。让我们从我如何在使用 ResourceDictionary 而不是 Window 的 MVVM 应用程序中使用该类开始。

          ' Loaded and Unloaded events seems to be the only way to initialize a control created from a Resource Dictionary
      ' Loading document here because Loaded is the last available event to create a document
      Private Sub Rtb_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
          ' only good place to initialize RichTextBox.Document with DependencyProperty
          Dim rtb As RichTextBox = DirectCast(sender, RichTextBox)
          Try
              rtb.Document = RichTextBoxHelper.GetDocumentXaml(rtb)
          Catch ex As Exception
              Debug.WriteLine("Rtb_Loaded: Message:" & ex.Message)
          End Try
      End Sub
      
      ' Loaded and Unloaded events seems to be the only way to initialize a control created from a Resource Dictionary
      ' Free document being held by RichTextBox.Document by assigning New FlowDocument to RichTextBox.Document. Otherwise we'll see an of "Document belongs to another RichTextBox"
      Private Sub Rtb_Unloaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
          Dim rtb As RichTextBox = DirectCast(sender, RichTextBox)
          Dim fd As New FlowDocument
          RichTextBoxHelper.SetDocumentXaml(rtb, fd)
          Try
              rtb.Document = fd
          Catch ex As Exception
              Debug.WriteLine("PoemDocument.PoemDocumentView.PoemRtb_Unloaded: Message:" & ex.Message)
          End Try
      End Sub
      
      Public Class RichTextBoxHelper
          Inherits DependencyObject
      
          Public Shared Function GetDocumentXaml(ByVal depObj As DependencyObject) As FlowDocument
              Return depObj.GetValue(DocumentXamlProperty)
          End Function
      
          Public Shared Sub SetDocumentXaml(ByVal depObj As DependencyObject, ByVal value As FlowDocument)
              depObj.SetValue(DocumentXamlProperty, value)
          End Sub
      
          Public Shared ReadOnly DocumentXamlProperty As DependencyProperty = DependencyProperty.RegisterAttached("DocumentXaml", GetType(FlowDocument), GetType(RichTextBoxHelper), New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender Or FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, Sub(depObj, e)
                                                                                                                                                                                                                                                                                                                                         RegisterIt(depObj, e)
                                                                                                                                                                                                                                                                                                                                     End Sub))
      
      
          Private Shared Sub RegisterIt(ByVal depObj As System.Windows.DependencyObject, ByVal e As System.Windows.DependencyPropertyChangedEventArgs)
              Dim rtb As RichTextBox = DirectCast(depObj, RichTextBox)
              If rtb.IsLoaded Then
                  RemoveHandler rtb.TextChanged, AddressOf TextChanged
                  Try
                      rtb.Document = GetDocumentXaml(rtb)
                  Catch ex As Exception
                      Debug.WriteLine("RichTextBoxHelper.RegisterIt: ex:" & ex.Message)
                      rtb.Document = New FlowDocument()
                  End Try
                  AddHandler rtb.TextChanged, AddressOf TextChanged
              Else
                  Debug.WriteLine("RichTextBoxHelper: Unloaded control ignored:" & rtb.Name)
              End If
          End Sub
      
          ' When a RichTextBox Document changes, update the DependencyProperty so they're in sync.
          Private Shared Sub TextChanged(ByVal sender As Object, ByVal e As TextChangedEventArgs)
              Dim rtb As RichTextBox = TryCast(sender, RichTextBox)
              If rtb IsNot Nothing Then
                  SetDocumentXaml(sender, rtb.Document)
              End If
          End Sub
      
      End Class
      

      【讨论】:

        【解决方案7】:

        我知道这是一篇旧帖子,但请查看Extended WPF Toolkit。它有一个 RichTextBox 支持你正在尝试做的事情。

        【讨论】:

        • Extended WPF Toolkit 中的 RichTextBox 真的很慢,我不推荐它。
        • @ViktorLaCroix 你知道这只是 WPF RichTextBox 上面有一个额外的属性吗?
        • (跳转到 2017 年...)wpf 工具包 RichTextBox 可以直接处理富文本或纯文本。它似乎也比使用下面的辅助方法快得多(如果你只是复制/粘贴它会引发异常)
        • 他们的免费许可仅用于非商业用途。 ://
        【解决方案8】:

        伙计们,为什么要打扰所有的废话。这完美地工作。无需代码

        <RichTextBox>
            <FlowDocument>
                <Paragraph>
                    <Run Text="{Binding Mytextbinding}"/>
                </Paragraph>
            </FlowDocument>
        </RichTextBox>
        

        【讨论】:

        • 在我的例子中,没有'FlowDocument'标签是行不通的。
        • Text Run 的属性不是依赖属性,因此它甚至无法编译。只有依赖属性支持这样的绑定。
        • 这正是我所需要的。
        【解决方案9】:
         <RichTextBox>
             <FlowDocument PageHeight="180">
                 <Paragraph>
                     <Run Text="{Binding Text, Mode=TwoWay}"/>
                  </Paragraph>
             </FlowDocument>
         </RichTextBox>
        

        这似乎是迄今为止最简单的方法,并且没有显示在任何这些答案中。

        在视图模型中只有Text 变量。

        【讨论】:

        • 在我的例子中,这个解决方案在视图模型中垂直显示 Text 属性的文本,即每行一个 for。
        • 这就是我所需要的。谢谢!
        • 此解决方案与绑定到 Text 属性的常规 TextBox 有何不同?它破坏了支持格式的富文本框的目的,该格式使用此代码有效地关闭。
        • 这对我来说是完美的。越简单越好!
        【解决方案10】:

        https://stackoverflow.com/a/2989277/3001007krzysztof 的这个回答满足了我的大部分需求。但是该代码的一个问题(我面临的是),绑定不适用于多个控件。所以我用基于Guid 的实现更改了_recursionProtection。所以它也适用于同一窗口中的多个控件。

         public class RichTextBoxHelper : DependencyObject
            {
                private static List<Guid> _recursionProtection = new List<Guid>();
        
                public static string GetDocumentXaml(DependencyObject obj)
                {
                    return (string)obj.GetValue(DocumentXamlProperty);
                }
        
                public static void SetDocumentXaml(DependencyObject obj, string value)
                {
                    var fw1 = (FrameworkElement)obj;
                    if (fw1.Tag == null || (Guid)fw1.Tag == Guid.Empty)
                        fw1.Tag = Guid.NewGuid();
                    _recursionProtection.Add((Guid)fw1.Tag);
                    obj.SetValue(DocumentXamlProperty, value);
                    _recursionProtection.Remove((Guid)fw1.Tag);
                }
        
                public static readonly DependencyProperty DocumentXamlProperty = DependencyProperty.RegisterAttached(
                    "DocumentXaml",
                    typeof(string),
                    typeof(RichTextBoxHelper),
                    new FrameworkPropertyMetadata(
                        "",
                        FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                        (obj, e) =>
                        {
                            var richTextBox = (RichTextBox)obj;
                            if (richTextBox.Tag != null && _recursionProtection.Contains((Guid)richTextBox.Tag))
                                return;
        
        
                            // Parse the XAML to a document (or use XamlReader.Parse())
        
                            try
                            {
                                string docXaml = GetDocumentXaml(richTextBox);
                                var stream = new MemoryStream(Encoding.UTF8.GetBytes(docXaml));
                                FlowDocument doc;
                                if (!string.IsNullOrEmpty(docXaml))
                                {
                                    doc = (FlowDocument)XamlReader.Load(stream);
                                }
                                else
                                {
                                    doc = new FlowDocument();
                                }
        
                                // Set the document
                                richTextBox.Document = doc;
                            }
                            catch (Exception)
                            {
                                richTextBox.Document = new FlowDocument();
                            }
        
                            // When the document changes update the source
                            richTextBox.TextChanged += (obj2, e2) =>
                                {
                                    RichTextBox richTextBox2 = obj2 as RichTextBox;
                                    if (richTextBox2 != null)
                                    {
                                        SetDocumentXaml(richTextBox, XamlWriter.Save(richTextBox2.Document));
                                    }
                                };
                        }
                    )
                );
            }
        

        为了完整起见,让我从ray-burns 的原始答案https://stackoverflow.com/a/2641774/3001007 中再添加几行。这是帮助程序的使用方法。

        <RichTextBox local:RichTextBoxHelper.DocumentXaml="{Binding Autobiography}" />
        

        【讨论】:

          【解决方案11】:

          这是我的解决方案,基于 Ray Burns 的 DataBinding 答案并将 XAML 字符串转换为 RichTextBox-Document:

          视图模型

              TestText = @"<FlowDocument xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""><Paragraph><Bold>Hello World!</Bold></Paragraph></FlowDocument>";
          

          查看

          <RichTextBox local:RichTextBoxHelper.DocumentXaml="{Binding TestText}"/>
          

          RichTextBoxHelper

          public class RichTextBoxHelper : DependencyObject
          {
              public static string GetDocumentXaml(DependencyObject obj) { return (string) obj.GetValue(DocumentXamlProperty); }
          
              public static void SetDocumentXaml(DependencyObject obj,
                                                 string value)
              {
                  obj.SetValue(DocumentXamlProperty, value);
              }
          
              public static readonly DependencyProperty DocumentXamlProperty = DependencyProperty.RegisterAttached
              (
                  "DocumentXaml",
                  typeof(string),
                  typeof(RichTextBoxHelper),
                  new FrameworkPropertyMetadata
                  {
                      BindsTwoWayByDefault = true,
                      PropertyChangedCallback = (obj,
                                                 e) =>
                      {
                          var    richTextBox = (RichTextBox) obj;
                          var    xaml        = GetDocumentXaml(richTextBox);
                          Stream sm          = new MemoryStream(Encoding.UTF8.GetBytes(xaml));
                          richTextBox.Document = (FlowDocument) XamlReader.Load(sm);
                          sm.Close();
                      }
                  }
              );
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-02-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多