RichTextBox无法绑定属性的失败经验

8 篇文章 0 订阅

目录

前言

一、尝试一:使用DocumentXaml

二、尝试二:使用string和FlowDocument相互转化方式

三、使用嵌套Run方式


前言

RichTextBox无法在MVVM模式绑定属性,使其根据输入和赋值的内容变化。按照网上经验做了以下尝试,全以失败告终,并且每种方式的缺点各不同。如果大家都成功的案例,欢迎留言交流。

一、尝试一:使用DocumentXaml

参考网址:Richtextbox wpf绑定 | 那些遇到过的问题

失败原因:CurrentAlarmInputInfoStr为string类型,无法正常绑定属性,即赋值后页面无显示且页面输入后CurrentAlarmInputInfoStr值不更新。

<!--Xaml文件-->
<RichTextBox RichTextBoxHelper1:RichTextBoxHelper.DocumentXaml="{Binding CurrentAlarmInputInfoStr}" />
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace Dev_SING.Infrastructure.Controls.RichTextBox
{
    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()));
                        }
                    };
                }
            });
    }
}

二、尝试二:使用string和FlowDocument相互转化方式

参考网址:WPF RichTextBox·绑定数据_wpf textbox绑定数据-CSDN博客

失败原因:可以正常绑定属性读写内容,但是我这里绑定的是一个弹框的内容,用这种方式只能打开一次窗口,第二次及以后都无法打开。没有代码报错和其他问题,不知道为什么会影响第二个窗口打开。

 1.BinBindableRichTextBox类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace Dev_SING.Infrastructure.Controls.RicheTextBox
{
    public class BindableRichTextBox : RichTextBox
    {
        public new FlowDocument Document
        {
            get { return (FlowDocument)GetValue(DocumentProperty); }
            set { SetValue(DocumentProperty, value); }
        }
        // Using a DependencyProperty as the backing store for Document.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DocumentProperty =
            DependencyProperty.Register("Document", typeof(FlowDocument), typeof(BindableRichTextBox), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnDucumentChanged)));
        private static void OnDucumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RichTextBox rtb = (RichTextBox)d;
            rtb.Document = (FlowDocument)e.NewValue;
        }
    }
}

2.在Xmal中添加控件,CurrentAlarmInputInfo为FlowDocument类型。

<RichTextBoxHelper1:BindableRichTextBox Document="{Binding CurrentAlarmInputInfo, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">

3.ViewModel

private FlowDocument currentAlarmInputInfo = new FlowDocument();

public FlowDocument CurrentAlarmInputInfo { get => currentAlarmInputInfo; set { currentAlarmInputInfo = value; OnPropertyChanged(() => CurrentAlarmInputInfo); } }

4.将字符串转换成FlowDocument

/// <summary>
/// 将字符串转换成FlowDocument
/// </summary>
/// <param name="str">原始字符串</param>
/// <param name="fld">要被赋值的Flowdocument</param>
/// <param name="par">要添加到Flowdocument里的Paragraph</param>
public void StrToFlDoc(string str, Paragraph par)
{
     //Paragraph par = new Paragraph();
     //当递归结束以后,也就是长度为0的时候,就跳出
     if (str.Length <= 0)
     {
          CurrentAlarmInputInfo.Blocks.Add(par);
          return;
     }
     //如果字符串里不存在[时,则直接添加内容
     if (!str.Contains('['))
     {
           par.Inlines.Add(new Run(str));
           str = str.Remove(0, str.Length);
           StrToFlDoc(str, par);
     }
     else
     {   
           //设置字符串长度
           int strLength = str.Length;
           par.Inlines.Add(new Run(GetTextByRegex(str)));
           str = str.Remove(0, GetTextByRegex(str).Length);
           StrToFlDoc(str, par);                
      }
}

/// <summary>
/// 获取文本信息
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private string GetTextByRegex(string str)
{
      string text = Regex.Match(str, "^.*?(?=\\[)").Value;
      return text;
}

5.将Document里的值都换成String

        /// <summary>
        /// 将Document里的值都换成String
        /// </summary>
        public string GetSendMessage(FlowDocument fld)
        {
            if (fld == null)
            {
                return string.Empty;
            }
            string resutStr = string.Empty;
            foreach (var root in fld.Blocks)
            {
                foreach (var item in ((Paragraph)root).Inlines)
                {
                    if (item is Run)
                    {
                        resutStr += ((Run)item).Text;
                    }
                }
            }
            return resutStr;
        }

三、使用嵌套Run方式

失败原因:CurrentAlarmInputInfoStr为string类型,正常绑定读写属性。存在一个问题,在第一次输入内容保存后,下次RichTextBox被赋值上次的已保存的内容可以正常显示,但是再进行修改的时候,必须将RichTextBox全部内容删除输入才可以写入CurrentAlarmInputInfoStr,否则只修改一部分内容继续编辑的话CurrentAlarmInputInfoStr还是上次保存的内容,未改变。

1.Xaml

        <RichTextBox x:Name="AlarmInputRichTB">
                     <FlowDocument>
                         <Paragraph>
                              <Run Text="{Binding CurrentAlarmInputInfoStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
                            </Paragraph>
                     </FlowDocument>
       </RichTextBox>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值