昨日の続き?
BringIntoViewなし
Thumbを移動させてもスクロール位置が変化しないので見えなくなってしまう
BringIntoViewあり
Thumbの移動後にBringIntoViewを実行しているので、Thumbの位値に合わせてスクロール位置が変化している
FrameworkElement.BringIntoView メソッド (System.Windows) | Microsoft Learn
learn.microsoft.com
より
この要素が含まれているスクロール可能な領域内に、この要素を表示することを試みます。
テストアプリのコード
2024WPF/20241218_ScrollViewer_BringIntoView at master · gogowaten/2024WPF
github.com
環境
- Windows 10 Home バージョン 22H2
- Visual Studio Community 2022 Version 17.12.3
- WPF
- C#
- .NET 8.0
MainWindow.xaml
<Window x:Class="_20241218_ScrollViewer_BringIntoView.MainWindow" 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" xmlns:local="clr-namespace:_20241218_ScrollViewer_BringIntoView" mc:Ignorable="d" Title="MainWindow" Height="280" Width="440"> <Window.Resources> <Style TargetType="Thumb"> <Setter Property="Width" Value="100"/> <Setter Property="Height" Value="100"/> <Setter Property="Focusable" Value="True"/> <EventSetter Event="DragDelta" Handler="Thumb_DragDelta"/> <EventSetter Event="KeyDown" Handler="Thumb_KeyDown"/> <EventSetter Event="KeyUp" Handler="Thumb_KeyUp"/> <EventSetter Event="PreviewMouseDown" Handler="Thumb_PreviewMouseDown"/> <EventSetter Event="PreviewMouseUp" Handler="Thumb_PreviewMouseUp"/> </Style> </Window.Resources> <Grid Background="PaleGreen"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition Width="120"/> </Grid.ColumnDefinitions> <ScrollViewer x:Name="MyScroll" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <Canvas x:Name="MyCanvas" Width="500" Height="500" Background="ForestGreen" KeyboardNavigation.TabNavigation="Cycle"> <Thumb Canvas.Left="50" Canvas.Top="50"/> <Thumb Canvas.Left="160" Canvas.Top="100"/> </Canvas> </ScrollViewer> <Grid Grid.Column="1" Margin="20"> <Grid.Background> <VisualBrush Visual="{Binding ElementName=MyCanvas}" Stretch="Uniform"/> </Grid.Background> </Grid> </Grid> </Window>
Canvasで指定しているKeyboardNavigation.TabNavigation="Cycle"は
タブキーでのフォーカス移動を自身の子要素内で循環させる
gogowaten.hatenablog.com
MainWindow.xaml.cs
using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; namespace _20241218_ScrollViewer_BringIntoView { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } /// <summary> /// マウスドラッグ移動 /// </summary> private void Thumb_DragDelta(object sender, DragDeltaEventArgs e) { if (sender is Thumb t) { Canvas.SetLeft(t, Canvas.GetLeft(t) + e.HorizontalChange); Canvas.SetTop(t, Canvas.GetTop(t) + e.VerticalChange); e.Handled = true; } } /// <summary> /// 方向キーの方向へ10ピクセル移動 /// </summary> private void Thumb_KeyDown(object sender, KeyEventArgs e) { if (sender is Thumb t) { if (e.Key == Key.Left) { Canvas.SetLeft(t, Canvas.GetLeft(t) - 10); e.Handled = true; } else if (e.Key == Key.Right) { Canvas.SetLeft(t, Canvas.GetLeft(t) + 10); e.Handled = true; } else if (e.Key == Key.Up) { Canvas.SetTop(t, Canvas.GetTop(t) - 10); e.Handled = true; } else if (e.Key == Key.Down) { Canvas.SetTop(t, Canvas.GetTop(t) + 10); e.Handled = true; } } } /// <summary> /// キーが離されたとき /// BringIntoViewを実行することで、Thumbが見える位置までスクロールする /// </summary> private void Thumb_KeyUp(object sender, KeyEventArgs e) { if (sender is Thumb t) { t.BringIntoView(); } } /// <summary> /// マウスボタン押したとき、 /// フォーカスを無効化することで、 /// Thumbの表示位置(スクロール位置)と /// マウスカーソルの位置に違和感がなくなり、ドラッグ移動動作も自然になる /// </summary> private void Thumb_PreviewMouseDown(object sender, MouseButtonEventArgs e) { if (sender is Thumb t) { t.Focusable = false; } } /// <summary> /// マウスボタンを離したとき /// フォーカスを有効化してからフォーカスする /// </summary> private void Thumb_PreviewMouseUp(object sender, MouseButtonEventArgs e) { if (sender is Thumb t) { t.Focusable = true; t.Focus(); } } } }
PreviewMouseDownとPreviewMouseUpでの処理は昨日の記事から
参照したところ
wpf コントロール - WPF ScrollViewer が認識されたコンテンツに自動的にスクロールするのを停止する - Stack Overflow
stackoverflow.com
ここでBringIntoViewってのがあることを知った
目的は今回の逆だけど、スクロールの制御って面では同じ
感想
知っていればなんてことないけど、その存在を知るまでが難しかった
関連記事
次のWPF記事
WPF、Canvasの拡大表示時の子要素のドラッグ移動距離とぼやけ表示の解消 - 午後わてんのブログ
13日後
WPF、この一ヶ月でのカスタムコントロールThumbのマウスドラッグ移動のまとめ - 午後わてんのブログ
gogowaten.hatenablog.com