諸事情による調査。非表示にした ScrollViewer の ScrollBar と、外側に配置して表示している ScrollBar のスクロール位置を同期する。
<UserControl x:Class="VirtualScrollSample.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="20" /> </Grid.ColumnDefinitions> <ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Hidden" Name="Container"> <StackPanel> <Grid Background="Orange" Height="100" /> <Grid Background="Blue" Height="100" /> <Grid Background="Yellow" Height="100" /> <Grid Background="Green" Height="100" /> <Grid Background="AliceBlue" Height="100" /> <Grid Background="Coral" Height="100" /> <Grid Background="Beige" Height="100" /> <Grid Background="Black" Height="100" /> <Grid Background="BlanchedAlmond" Height="100" /> <Grid Background="Red" Height="100" /> <Grid Background="Blue" Height="100" /> <Grid Background="Yellow" Height="100" /> <Grid Background="Green" Height="100" /> <Grid Background="AliceBlue" Height="100" /> <Grid Background="Coral" Height="100" /> <Grid Background="Beige" Height="100" /> <Grid Background="Black" Height="100" /> <Grid Background="BlanchedAlmond" Height="100" /> </StackPanel> </ScrollViewer> <ScrollBar Grid.Column="1" Grid.Row="1" Name="ContainerScrollBar" Scroll="ContainerScrollBar_Scroll"/> </Grid> </UserControl>
using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; namespace VirtualScrollSample { public partial class MainPage : UserControl { /// <summary> /// /// </summary> public MainPage() { InitializeComponent(); SetBinding(OffsetProperty, new Binding("VerticalOffset") { Source = Container, Mode = BindingMode.OneWay, }); } /// <summary> /// ScrollViewer のスクロール位置を ScrollBar に反映する /// </summary> public static readonly DependencyProperty OffsetProperty = DependencyProperty.Register( "Offset", typeof(double), typeof(MainPage), new PropertyMetadata(0d, (d, e) => { MainPage page = d as MainPage; double offset = (double)e.NewValue / page.Container.ScrollableHeight; page.ContainerScrollBar.Value = offset; })); /// <summary> /// ScrollViewer のスクロール位置 /// </summary> private double Offset { get { return (double)this.GetValue(OffsetProperty); } set { this.SetValue(OffsetProperty, value); } } /// <summary> /// ScrollBar のスクロール位置を ScrollViewer に反映する /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ContainerScrollBar_Scroll(object sender, ScrollEventArgs e) { double offset = Container.ScrollableHeight * e.NewValue; Container.ScrollToVerticalOffset(offset); } } }