RichEditBox
(editor) とGrid
(MarginNotes)を備えた Windows ストア アプリを持っています。
2 つの要素の垂直スクロール位置を常に一致させる必要があります。これの目的は、ユーザーがドキュメントの余白にメモを追加できるようにすることです。
カーソル位置に基づいてメモの配置を既に把握しています。メモが追加されると、カーソルまでのすべてのテキストが選択されます。その選択はRichEditBox
、 内の2 番目の invisible に追加されStackPanel
ます。次にActualHeight
、グリッド内のノートの位置を示すこのコントロールの を取得します。
私の問題は、RichEditBox
上下にスクロールすると、Grid
それに応じてスクロールしないことです。
最初のテクニック
両方を の中に入れて、ScrollViewer
スクロールを無効にしてみました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
カーソルで自動的にスクロールしません。
カーソルの位置を確認し、それをエディターの高さと比較し、それにVerticalOffset
応じてスクロールを調整する C# コードを追加してみました。これはうまくいきましたが、信じられないほど遅かったです。最初はKeyUp
、文を入力するとアプリが停止するイベントでそれを持っていました。その後、5 秒のタイマーを設定しましたが、それでもアプリのパフォーマンスが低下し、カーソルが見えなくなってからRichEditBox
スクロールするまでに 5 秒の遅延が発生する可能性がありました。
第二のテクニック
MarginNotes
また、独自のを入れて、自分のイベントに基づいてScrollViewer
プログラムで設定しようとしました。VerticalOffset
RichEditBox
ViewChanged
<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
高速スクロール後に位置がずれることもありました。