我想加载大 .rtf 文件并滚动到其中的特定段落。
所以我做了这样的事情:
private FlowDocument GenerateDocument(string path)
{
var doc = new FlowDocument();
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read))
{
var content = new TextRange(doc.ContentStart, doc.ContentEnd);
content.Load(fs, DataFormats.Rtf);
}
return doc;
}
Run Code Online (Sandbox Code Playgroud)
然后,我查找已添加书签的段落并想要滚动到那里。像这样的东西:
private void ScrollToBookmark(string bookmark)
{
Paragraph p = LookUp(bookmark);
if (p != null) p.BringIntoView();
}
Run Code Online (Sandbox Code Playgroud)
LookUp 是一个查找所需段落的功能,它运行良好,并返回先前加载的文档中的段落。
而且……什么也没发生。有小费吗?
我使用 FlowDocumentReader 来显示我的 Flowdocument。BringIntoView 在 ScrollMode 和 PageMode 下均不起作用。
通过逻辑树直接访问 FlowDocumentReader 的滚动查看器并对其进行操作不是一种选择。我只是不知道在哪里滚动,并且如果可能的话,宁愿不使用任何“黑客”。
好吧,我发现了一个问题。
问题是,当您加载新的 FlowDocument 时,段落会异步加载,因此如果您在加载文档后立即调用 paragraph.BringIntoView() - 段落尚不存在,因此什么也不会发生。
以下是一些详细信息:https ://support.microsoft.com/en-us/kb/959084
您需要检查 paragraph.IsLoaded 属性,如果尚未加载,则需要捕获 Loaded 事件并在那里调用 BringIntoView() 。
这是我使用的代码,它运行得很好:
private void BringToViewParagraph(Paragraph paragraph)
{
if (paragraph.IsLoaded) paragraph.BringIntoView();
else
{
paragraph.Loaded += paragraphLoaded;
}
}
void paragraphLoaded(object sender, RoutedEventArgs e)
{
Paragraph paragraph = (Paragraph)sender;
paragraph.Loaded -= paragraphLoaded;
paragraph.BringIntoView();
}
Run Code Online (Sandbox Code Playgroud)