Определить, пустой ли RichTextBox - PullRequest
12 голосов
/ 29 апреля 2011

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

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

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

Ответы [ 5 ]

14 голосов
/ 29 апреля 2011

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

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;
}
3 голосов
/ 30 октября 2015

Ответ Х.Б. бесполезен, если вам необходимо различать изображения и пробелы. Вы можете использовать что-то вроде этот ответ для проверки изображений.

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

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

2 голосов
/ 10 мая 2014

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

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

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

0 голосов
/ 20 октября 2017

Вот расширение идеи Х.Б., которая работает как с текстом, так и с изображениями .

Я обнаружил, что разница всегда> 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 для базовой линии.

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

0 голосов
/ 01 ноября 2015

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

    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

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

...