【发布时间】:2011-08-15 02:20:40
【问题描述】:
检测 WPF RichTextBox/FlowDocument 是否为空的最佳方法是什么?
如果文档中仅存在文本,则以下内容有效。如果它包含 UIElement,则不是
new TextRange(Document.ContentStart, Document.ContentEnd).IsEmpty
【问题讨论】:
标签: wpf richtextbox flowdocument
检测 WPF RichTextBox/FlowDocument 是否为空的最佳方法是什么?
如果文档中仅存在文本,则以下内容有效。如果它包含 UIElement,则不是
new TextRange(Document.ContentStart, Document.ContentEnd).IsEmpty
【问题讨论】:
标签: wpf richtextbox flowdocument
这是 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 作为基线。
如果没有文本字符,长度检查可能会很昂贵,但它们粘贴在一个大图像中。
【讨论】:
首先 - 感谢 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
可能还有其他检查要做,但这至少包括文本、图像和表格。
【讨论】:
如果您需要区分图像和空白,则 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;
}
这似乎很费力,而且可能仍不适用于所有场景。但我找不到更好的方法。
【讨论】:
如果您不将任何内容放入 RTB,则上述答案有效。但是,如果您只是删除内容,RTB 往往会返回一个空段落,而不是一个完全空的字符串。因此,在这种情况下,这更可靠:
string text = new TextRange(Document.ContentStart, Document.ContentEnd).Text;
return !String.IsNullOrWhiteSpace(text);
当然,这只适用于文本内容。
【讨论】:
您可以比较指针,这不太可靠:
var start = rtb.Document.ContentStart;
var end = rtb.Document.ContentEnd;
int difference = start.GetOffsetToPosition(end);
如果 RTB 已加载,则计算结果为 2,如果已再次输入和删除内容,则计算结果为 4。
如果 RTB 被完全清除,例如通过select all -> 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;
}
【讨论】: