Detect if a RichTextBox is empty

泪湿孤枕 提交于 2019-12-04 00:32:03

You could compare the pointers, which is not all too reliable:

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

This evaluates to 2 if the RTB is loaded, and 4 if content has been entered and removed again.
If the RTB is completely cleared out e.g. via select all -> delete the value will be 0.


In the Silverlight reference on MSDN another method is found which can be adapted and improved to:

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

H.B.'s answer isn't useful if you need to distinguish between images and whitespace. You can use something like this answer to check for images.

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

This seems laborious, and still probably isn't correct for all scenarios. But I couldn't find any better way.

The answer above works if you don't put anything into the RTB. However, if you simply delete the contents, the RTB tends to return a single, empty paragraph, not a completely empty string. So, this is more reliable in such cases:

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

This only applies to textual contents, of course.

First - thank you to McGarnagle - their answer got me going in the right direction. However for whatever reason their image check didn't work for me. This is what I ended up doing:

    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

there may be other checks to do, but this at least covers text, images and tables.

Here's an extension of H.B.'s idea that works with both text and images.

I found that difference is always >4 whenever the RTB has text. However, if you only paste an image it is 3. To combat this i look at the string length of the raw rtf string.

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

Through my testing i found that an empty box with no chars has a length of 270. If i even paste in an image that's only 1 pixel in size it balloons to 406.

I played with toggling on various formatting options without typing any letters and haven't gotten close to 300, so I went with 350 for the baseline.

The length check could be expensive if there are no textual characters, but they pasted in a massive image.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!