我有一个带有RichEditBox
(editor) 和Grid
(MarginNotes) 的 Windows Store 应用程序。
我需要始终匹配两个元素的垂直滚动位置。这样做的目的是允许用户在文档的边缘添加注释。
我已经根据光标位置计算出注释定位 - 添加注释时,文本选择由光标之前的所有内容组成。然后将该选择添加到 aRichEditBox
内的第二个不可见的StackPanel
. 然后我得到ActualHeight
这个控件,它给了我在网格中的注释位置。
我的问题是,当我RichEditBox
向上和向下滚动时,Grid
不会相应地滚动。
第一种技术
我尝试将它们都放在 aScrollViewer
中,并禁用滚动RichEditBox
<ScrollViewer x:Name="EditorScroller"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="{Binding *" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid x:Name="MarginNotes" Grid.Column="0" HorizontalAlignment="Right"
Height="{Binding ActualHeight, ElementName=editor}">
</Grid>
<StackPanel Grid.Column="1">
<RichEditBox x:Name="margin_helper" Opacity="0" Height="Auto"></RichEditBox>
</StackPanel>
<RichEditBox x:Name="editor" Grid.Column="1" Height="Auto"
ScrollViewer.VerticalScrollBarVisibility="Hidden" />
</Grid>
</ScrollViewer>
当我滚动到RichEditBox
控件的底部并按几次 Enter 时,光标消失了。ScrollViewer
不会随光标自动滚动。
我尝试添加 C# 代码来检查光标的位置,将其VerticalOffset
与编辑器的高度和高度进行比较,然后相应地调整滚动。这有效,但速度非常慢。最初,KeyUp
当我键入一个句子时,我将它用于使应用程序停止的事件。之后我将其设置为 5 秒计时器,但这仍然会降低应用程序的性能,并且还意味着在光标消失和RichEditBox
滚动之间可能会有 5 秒的延迟。
第二种技术
我还尝试放入MarginNotes
它自己的ScrollViewer
,并以编程方式设置VerticalOffset
基于 my RichEditBox
sViewChanged
事件。
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="{Binding *" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="MarginScroller" Grid.Column="0"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid x:Name="MarginNotes" HorizontalAlignment="Right"
Height="{Binding ActualHeight, ElementName=editor}">
</Grid>
</ScrollViewer>
<StackPanel Grid.Column="1">
<RichEditBox x:Name="margin_helper" Opacity="0" Height="Auto"></RichEditBox>
</StackPanel>
<RichEditBox x:Name="editor" Grid.Column="1" Height="Auto"
Loaded="editor_loaded" SizeChanged="editor_SizeChanged" />
</Grid>
相关事件处理程序
void editor_Loaded(object sender, RoutedEventArgs e)
{
// setting this in the OnNavigatedTo causes a crash, has to be set here.
// this uses WinRTXAMLToolkit as suggested by Nate Diamond to find the
// ScrollViewer and add the event handler
editor.GetFirstDescendantOfType<ScrollViewer>().ViewChanged += editor_ViewChanged;
}
private void editor_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
// when the RichEditBox scrolls, scroll the MarginScroller the same amount
double editor_vertical_offset = ((ScrollViewer)sender).VerticalOffset;
MarginScroller.ChangeView(0, editor_vertical_offset, 1);
}
private void editor_SizeChanged(object sender, SizeChangedEventArgs e)
{
// when the RichEditBox size changes, change the size of MarginNotes to match
string text = "";
editor.Document.GetText(TextGetOptions.None, out text);
margin_helper.Document.SetText(TextSetOptions.None, text);
MarginNotes.Height = margin_helper.ActualHeight;
}
这有效,但相当滞后,因为ViewChanged
在滚动停止后,直到事件触发后才应用滚动。我尝试使用该ViewChanging
事件,但由于某种原因它根本没有触发。此外,在Grid
快速滚动后有时会出现错误定位。