检测 RichTextBox 是否为空

发布于 2024-11-03 19:38:10 字数 191 浏览 6 评论 0原文

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

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

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

What is the best way to detect if a WPF RichTextBox/FlowDocument is empty?

The following works if only text is present in the document. Not if it contains UIElement's

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

远山浅 2024-11-10 19:38:11

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

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

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


MSDN 上的 Silverlight 参考中,另一个发现可以调整和改进的方法:

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

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;
}
池木 2024-11-10 19:38:11

如果您需要区分图像和空白,HB 的答案没有用。您可以使用此答案之类的内容来检查图像。

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

这看起来很费力,而且可能仍然不适用于所有情况。但我找不到更好的办法。

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.

叫嚣ゝ 2024-11-10 19:38:11

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

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

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

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.

千纸鹤带着心事 2024-11-10 19:38:11

首先 - 感谢 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

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

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.

机场等船 2024-11-10 19:38:11

这是 HB 想法的延伸,适用于文本和图像

我发现只要 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 作为基线。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文