質問
WPF ScrollViewerのスクロール量を変更することはできますか?マウスホイールまたはスクロールビューアの矢印を使用するときに、インクリメンタルスクロールの量を変更できるように、スクロールビューアを変更できるかどうかだけを考えています。
解決
簡単な答えは、カスタムスクロールコードを記述せずにこれを行う方法はありませんが、それほど難しくないことを恐れないでください。
ScrollViewerは、物理ユニット(ピクセルなど)を使用してスクロールするか、IScrollInfo実装を使用して論理ユニットを使用することで機能します。これは、 CanContentScrollプロパティの設定によって制御されます falseの値は、「物理ユニットを使用してコンテンツをスクロールする」ことを意味します。 trueの値は「コンテンツを論理的にスクロールする」ことを意味します。
では、ScrollViewerはどのようにコンテンツを論理的にスクロールしますか? IScrollInfo実装と通信する。だから、誰かが論理的なアクションを実行したときに、パネルのコンテンツがどれだけスクロールするかを引き継ぐことができます。 IScrollInfoのドキュメントをご覧くださいスクロールを要求できる測定のすべての論理単位のリストを取得しますが、マウスホイールに言及したので、MouseWheelUp / Down / Left / Rightメソッドに最も関心があります。
他のヒント
これは、マウスホイールの感度を調整するためのデータバインド可能な SpeedFactor
プロパティを持つ、シンプルで完全で機能する WPF ScrollViewer
クラスです。 SpeedFactor
を1.0に設定すると、WPF ScrollViewer
と同じ動作を意味します。依存関係プロパティのデフォルト値は 2.5 です。これにより、ホイールを非常に高速にスクロールできます。
もちろん、 SpeedFactor
プロパティ自体にバインドすることで、ユーザーが乗数を簡単に制御できるようにするために、追加の便利な機能を作成することもできます。
public class WheelSpeedScrollViewer : ScrollViewer
{
public static readonly DependencyProperty SpeedFactorProperty =
DependencyProperty.Register(nameof(SpeedFactor),
typeof(Double),
typeof(WheelSpeedScrollViewer),
new PropertyMetadata(2.5));
public Double SpeedFactor
{
get { return (Double)GetValue(SpeedFactorProperty); }
set { SetValue(SpeedFactorProperty, value); }
}
protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
{
if (!e.Handled &&
ScrollInfo is ScrollContentPresenter scp &&
ComputedVerticalScrollBarVisibility == Visibility.Visible)
{
scp.SetVerticalOffset(VerticalOffset - e.Delta * SpeedFactor);
e.Handled = true;
}
}
};
約3200個のデータ項目の「高速マウスホイールスクロール」の完全なXAMLデモ:
<UserControl x:Class="RemoveDuplicateTextLines.FastScrollDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApp"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<local:WheelSpeedScrollViewer VerticalScrollBarVisibility="Auto">
<ListBox ItemsSource="{Binding Source={x:Type sys:Object},Path=Assembly.DefinedTypes}" />
</local:WheelSpeedScrollViewer>
</UserControl>
高速マウスホイール:
スクロールビューアーに動作を実装できます。私の場合、 CanContentScroll
は機能しませんでした。以下の解決策は、マウスホイールでスクロールしたり、スクロールバーをドラッグしたりするのに有効です。
public class StepSizeBehavior : Behavior<ScrollViewer>
{
public int StepSize { get; set; }
#region Attach & Detach
protected override void OnAttached()
{
CheckHeightModulesStepSize();
AssociatedObject.ScrollChanged += AssociatedObject_ScrollChanged;
base.OnAttached();
}
protected override void OnDetaching()
{
AssociatedObject.ScrollChanged -= AssociatedObject_ScrollChanged;
base.OnDetaching();
}
#endregion
[Conditional("DEBUG")]
private void CheckHeightModulesStepSize()
{
var height = AssociatedObject.Height;
var remainder = height%StepSize;
if (remainder > 0)
{
throw new ArgumentException(<ScrollViewer MaxHeight="248"
VerticalScrollBarVisibility="Auto">
<i:Interaction.Behaviors>
<behaviors:StepSizeBehavior StepSize="62" />
</i:Interaction.Behaviors>
quot;{nameof(StepSize)} should be set to a value by which the height van be divised without a remainder.");
}
}
private void AssociatedObject_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
const double stepSize = 62;
var scrollViewer = (ScrollViewer)sender;
var steps = Math.Round(scrollViewer.VerticalOffset / stepSize, 0);
var scrollPosition = steps * stepSize;
if (scrollPosition >= scrollViewer.ScrollableHeight)
{
scrollViewer.ScrollToBottom();
return;
}
scrollViewer.ScrollToVerticalOffset(scrollPosition);
}
}
次のように使用します:
<*>scrollbar1.ValueChangedの整数を確保するためにこれを行いました:
scrollbar1.Value = Math.Round(scrollbar1.Value, 0, MidpointRounding.AwayFromZero)