无论如何要获取FlowDocument中Run元素的水平位置(像素)和垂直位置(像素)?
编辑: 我需要做的就是滚动到该位置并使其成为FlowDocument的顶行。
答案 0 :(得分:2)
回答您的问题
获取文档中内容元素位置所需的代码都是.NET内部的,而不是公开的。您需要访问IContentHost实现,内置文档查看器不会公开显示该实现。所以,没有支持的方式来做你要求的。
解决您的实际问题
有一种方法可以实现将元素滚动到视图顶部所需的结果。你想要做的是滚动到文档的末尾,然后在你想要的顶部元素上调用BringIntoView。
应用程序中有multiple ways a FlowDocument can be displayed。如何处理滚动取决于您使用哪个控件来呈现FlowDocument
。
RichTextBox
中,使用ScrollToEnd方法。在FlowDocumentScrollViewer
中,您需要获取其内部ScrollViewer并在其上调用ScrollToBottom。 (您必须等到控件加载后再从中获取模板部分。)
private void MyControl_Loaded(object sender, RoutedEventArgs e)
{
mScrollViewer = mViewer.Template.FindName("PART_ContentHost", mViewer) as ScrollViewer;
}
在FlowDocumentReader
中,这个过程有点复杂。
加载控件后,注册ViewingMode属性的更改并运行处理程序一次以考虑起始值:
private void MyControl_Loaded(object sender, RoutedEventArgs e)
{
var descriptor = DependencyPropertyDescriptor.FromProperty(FlowDocumentReader.ViewingModeProperty, typeof(FlowDocumentReader));
descriptor.AddValueChanged(mReader, (s, a) => Reader_ViewModeChanged());
Reader_ViewModeChanged();
}
在处理程序中,深入查找ScrollViewer
。它仅在ViewingMode
设置为Scroll
时才会出现:
private void Reader_ViewModeChanged()
{
mScrollViewer = null;
if (mReader.ViewingMode == FlowDocumentReaderViewingMode.Scroll)
{
var contentHost = mReader.Template.FindName("PART_ContentHost", mReader) as DependencyObject;
if (contentHost != null && VisualTreeHelper.GetChildrenCount(contentHost) > 0)
{
var documentScrollViewer = VisualTreeHelper.GetChild(contentHost, 0) as FlowDocumentScrollViewer;
if (documentScrollViewer != null)
{
documentScrollViewer.ApplyTemplate();
mScrollViewer = documentScrollViewer.Template.FindName("PART_ContentHost", documentScrollViewer) as ScrollViewer;
}
}
}
}
获得ScrollViewer
后,您可以在需要时致电ScrollToBottom。
现在,滚动到文档的底部,然后在Run
上调用BringIntoView,它应位于视图的顶部。
答案 1 :(得分:1)
不会将其置于顶部,只需在运行时调用BringIntoView即可。保存对Run的引用。
答案 2 :(得分:0)
可能已经晚了,但是我仍然想分享我在WPF中进行DID的方式。 您需要一个偏移量。
如上所述:流程给了你
flow.ScrollToHome(); // Bottom
但也给出了:ScrollToVerticalOffset (get from Rect)
如果您有索引(字符/行的偏移量)-您可以在保存的数据中找到它,或者使用flow.Selection.Start/End
获取TextPointer
TextPointer t_st = flow.Selection.Start;
double offset = flow.Document.ContentStart.GetOffsetToPosition(t_st);
private void gotoOffset(double offset)
{
TextPointer myTextPointer1 = flow.Document.ContentStart.GetPositionAtOffset((int)offset);
flow.Selection.Select(myTextPointer1, myTextPointer1);
flow.Focus();
Rect screenPos2 = myTextPointer1.GetCharacterRect(LogicalDirection.Forward);
double offset2 = screenPos2.Top;
Thread.Sleep(100);
flow.ScrollToVerticalOffset(offset2);
flow.Focus();
}
作为上面的代码,我们从TextPointer,Textpointer获取Rect,并从Offset获取。 焦点只是为了确保将光标放置在正确的位置。
有时候,当您跳到许多偏移时,就会发生此问题。
我建议在跳动之前触发flow.ScrollToHome();
(因为从头开始,此ScrollToVerticalOffset为true,所以没有一行)