1. ホーム
  2. c#

[解決済み] リッチテキストボックス wpf バインディング

2023-07-16 14:51:44

質問

のデータバインディングを行うには Document をWPFの RichtextBox から派生したもので、これまでに2つの解決策を見ました。 RichtextBox から派生させ、さらに DependencyProperty を追加し、さらに"proxy"で解決します。

最初も2番目も満足のいくものではありません。どなたか別の解決策、または代わりに、以下のことが可能な市販の RTF コントロールをご存知ですか? データバインディング ? 通常の TextBox は、テキストフォーマットが必要なので、代替にはなりません。

何かいい案はありませんか?

どのように解決するのですか?

この回答で、私の要求のほとんどが満たされました。 https://stackoverflow.com/a/2989277/3001007 によって クシシュトフ . しかし、そのコードで1つの問題がありました(私が直面した)、バインディングは、複数のコントロールで動作しません。そこで、私は _recursionProtectionGuid をベースにした実装です。そのため、同じウィンドウに複数のコントロールがある場合でも同様に動作しています。

 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));
                            }
                        };
                }
            )
        );
    }

完全を期すために、元の回答からさらに数行を追加します。 https://stackoverflow.com/a/2641774/3001007 によって レイバーン . ヘルパーの使い方はこのようになります。

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