【问题标题】:Detect if a RichTextBox is empty检测 RichTextBox 是否为空
【发布时间】:2011-08-15 02:20:40
【问题描述】:

检测 WPF RichTextBox/FlowDocument 是否为空的最佳方法是什么?

如果文档中仅存在文本,则以下内容有效。如果它包含 UIElement,则不是

new TextRange(Document.ContentStart, Document.ContentEnd).IsEmpty

【问题讨论】:

    标签: wpf richtextbox flowdocument


    【解决方案1】:

    这是 H.B. 想法的扩展,适用于文本和图像

    我发现只要 RTB 有文本,差异总是 >4。但是,如果您只粘贴图像,则为 3。为了解决这个问题,我查看了原始 rtf 字符串的字符串长度。

    var start = Document.ContentStart;
    var end = Document.ContentEnd;
    var difference = start.GetOffsetToPosition(end);
    
    HasText = difference > 4 || GetRtfText().Length > 350;
    
    
    public string GetRtfText()
    {
      var tr = new TextRange(Document.ContentStart, Document.ContentEnd);
      using (var ms = new MemoryStream())
      {
        tr.Save(ms, DataFormats.Rtf);
        return Encoding.Default.GetString(ms.ToArray());
      }
    }
    

    通过我的测试,我发现一个没有字符的空框的长度为 270。如果我什至粘贴一个只有 1 像素大小的图像,它会膨胀到 406。

    我在不输入任何字母的情况下切换了各种格式选项,并且没有接近 300,所以我选择了 350 作为基线。

    如果没有文本字符,长度检查可能会很昂贵,但它们粘贴在一个大图像中。

    【讨论】:

      【解决方案2】:

      首先 - 感谢 McGarnagle - 他们的回答让我朝着正确的方向前进。但是无论出于何种原因,他们的图像检查对我不起作用。这就是我最终要做的:

          Private Function RichTextBoxIsEmpty(BYVAL rtb As RichTextBox) As Boolean
      
          Dim ReturnCode As Boolean = True
      
          Dim text As String = New TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd).Text
      
          If String.IsNullOrWhiteSpace(text) Then
      
              For Each block As Block In rtb.Document.Blocks
      
                  'check for an image
                  If TypeOf block Is Paragraph Then
                      Dim paragraph As Paragraph = DirectCast(block, Paragraph)
                      For Each inline As Inline In paragraph.Inlines
                          If TypeOf inline Is InlineUIContainer Then
                              Dim uiContainer As InlineUIContainer = DirectCast(inline, InlineUIContainer)
                              If TypeOf uiContainer.Child Is Image Then
                                  ReturnCode = False
                                  Exit For
                              End If
                          End If
                      Next
                  End If
      
                  ' Check for a table
                  If TypeOf block Is Table Then
                      ReturnCode = False
                      Exit For
                  End If
      
              Next
      
          Else
      
              ReturnCode = False
      
          End If
      
          Return ReturnCode
      
      End Function
      

      可能还有其他检查要做,但这至少包括文本、图像和表格。

      【讨论】:

        【解决方案3】:

        如果您需要区分图像和空白,则 H.B. 的答案没有用。您可以使用 this answer 之类的东西来检查图像。

        bool IsEmpty(Document document)
        {
            string text = new TextRange(Document.ContentStart, Document.ContentEnd).Text;
            if (string.IsNullOrWhiteSpace(text) == false)
                return false;
            else
            {
                if (document.Blocks.OfType<BlockUIContainer>()
                    .Select(c => c.Child).OfType<Image>()
                    .Any())
                return false;
            }
            return true;
        }
        

        这似乎很费力,而且可能仍不适用于所有场景。但我找不到更好的方法。

        【讨论】:

          【解决方案4】:

          如果您不将任何内容放入 RTB,则上述答案有效。但是,如果您只是删除内容,RTB 往往会返回一个空段落,而不是一个完全空的字符串。因此,在这种情况下,这更可靠:

          string text = new TextRange(Document.ContentStart, Document.ContentEnd).Text;
          return !String.IsNullOrWhiteSpace(text);
          

          当然,这只适用于文本内容。

          【讨论】:

            【解决方案5】:

            您可以比较指针,这不太可靠:

            var start = rtb.Document.ContentStart;
            var end = rtb.Document.ContentEnd;
            int difference = start.GetOffsetToPosition(end);
            

            如果 RTB 已加载,则计算结果为 2,如果已再次输入和删除内容,则计算结果为 4
            如果 RTB 被完全清除,例如通过select all -&gt; delete,值将是0


            Silverlight reference on MSDN 中找到了另一种可以调整和改进的方法:

            public bool IsRichTextBoxEmpty(RichTextBox rtb)
            {
                if (rtb.Document.Blocks.Count == 0) return true;
                TextPointer startPointer = rtb.Document.ContentStart.GetNextInsertionPosition(LogicalDirection.Forward);
                TextPointer endPointer = rtb.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward);
                return startPointer.CompareTo(endPointer) == 0;
            }
            

            【讨论】:

            • 即使 RichTextBox 为空,计数也是 1。
            • 我编辑了我的答案以展示另一种方法,但这有点奇怪。
            • 前 3 行对我有用。谢谢!即使剩下一个空格,你也不会得到 0 的差异。
            • 我希望得到类似 empty== count
            猜你喜欢
            • 2012-06-04
            • 1970-01-01
            • 2017-04-17
            • 2015-01-29
            • 1970-01-01
            • 1970-01-01
            • 2017-08-03
            • 2011-10-19
            • 1970-01-01
            相关资源
            最近更新 更多