Обнаружение, если RichTextBox пуст

Каков наилучший способ определить, пустой ли WPF RichTextBox/FlowDocument?

Следующее работает, если в документе присутствует только текст. Нет, если он содержит

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

Ответ 1

Вы можете сравнить указатели, которые не слишком надежны:

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

Это оценивается до 2, если загружается RTB, и 4, если содержимое было снова введено и удалено.
Если RTB полностью очищен, например, через select all -> delete значение будет 0.


В ссылка Silverlight на 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;
}

Ответ 2

H.B. ответ не полезен, если вам нужно различать изображения и пробелы. Вы можете использовать что-то вроде этого ответа для проверки изображений.

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

Это кажется трудоемким и, вероятно, не подходит для всех сценариев. Но я не мог найти лучшего способа.

Ответ 3

Ответ выше работает, если вы ничего не вкладываете в RTB. Однако, если вы просто удаляете содержимое, RTB имеет тенденцию возвращать один, пустой абзац, а не полностью пустую строку. Таким образом, это более надежно в таких случаях:

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

Это относится только к текстовому содержимому, конечно.

Ответ 4

Сначала - спасибо МакГарнаглу - их ответ заставил меня идти в правильном направлении. Однако по какой-то причине их проверка изображения не сработала для меня. Это то, что я закончил:

    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

могут быть другие проверки, но это, по крайней мере, охватывает текст, изображения и таблицы.

Ответ 5

Здесь расширение H.B. идея, которая работает как с текстом, так и с изображениями.

Я обнаружил, что разница всегдa > 4, когда RTB имеет текст. Однако, если вы вставляете только изображение, то оно равно 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 для базовой линии.

Проверка длины может быть дорогой, если текстовых символов нет, но они были вставлены в массивное изображение.

Ответ 6

if (textbox1->Text->Length == 0)
{
    //Do ANYTHING       
}