gpt4 book ai didi

c# - 使用 ScrollViewer 单击并拖动滚动

转载 作者:行者123 更新时间:2023-12-02 05:15:07 25 4
gpt4 key购买 nike

我想允许使用 ScrollViewer 单击并拖动滚动(即单击 ScrollViewer 中的任意位置并向上或向下拖动,它会相应地滚动)

我有一个 StackPanel 嵌套在 ScrollViewer 中,并且我已经有了滚动功能。我相信我在某个地方看到了那个答案,但我似乎再也找不到了。

这只能使用代码来完成。

最佳答案

this code from Matt Hamilton :

public class TouchScrolling : DependencyObject
{
public static bool GetIsEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
}

public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
}

public bool IsEnabled
{
get { return (bool)GetValue(IsEnabledProperty); }
set { SetValue(IsEnabledProperty, value); }
}

public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(TouchScrolling), new UIPropertyMetadata(false, IsEnabledChanged));

static Dictionary<object, MouseCapture> _captures = new Dictionary<object, MouseCapture>();

static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = d as ScrollViewer;
if (target == null) return;

if ((bool)e.NewValue)
{
target.Loaded += target_Loaded;
}
else
{
target_Unloaded(target, new RoutedEventArgs());
}
}

static void target_Unloaded(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Target Unloaded");

var target = sender as ScrollViewer;
if (target == null) return;

_captures.Remove(sender);

target.Loaded -= target_Loaded;
target.Unloaded -= target_Unloaded;
target.PreviewMouseLeftButtonDown -= target_PreviewMouseLeftButtonDown;
target.PreviewMouseMove -= target_PreviewMouseMove;

target.PreviewMouseLeftButtonUp -= target_PreviewMouseLeftButtonUp;
}

static void target_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var target = sender as ScrollViewer;
if (target == null) return;

_captures[sender] = new MouseCapture
{
VerticalOffset = target.VerticalOffset,
Point = e.GetPosition(target),
};
}

static void target_Loaded(object sender, RoutedEventArgs e)
{
var target = sender as ScrollViewer;
if (target == null) return;

System.Diagnostics.Debug.WriteLine("Target Loaded");

target.Unloaded += target_Unloaded;
target.PreviewMouseLeftButtonDown += target_PreviewMouseLeftButtonDown;
target.PreviewMouseMove += target_PreviewMouseMove;

target.PreviewMouseLeftButtonUp += target_PreviewMouseLeftButtonUp;
}

static void target_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var target = sender as ScrollViewer;
if (target == null) return;

target.ReleaseMouseCapture();
}

static void target_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (!_captures.ContainsKey(sender)) return;

if (e.LeftButton != MouseButtonState.Pressed)
{
_captures.Remove(sender);
return;
}

var target = sender as ScrollViewer;
if (target == null) return;

var capture = _captures[sender];

var point = e.GetPosition(target);

var dy = point.Y - capture.Point.Y;
if (Math.Abs(dy) > 5)
{
target.CaptureMouse();
}

target.ScrollToVerticalOffset(capture.VerticalOffset - dy);
}

internal class MouseCapture
{
public Double VerticalOffset { get; set; }
public Point Point { get; set; }
}

这里有一些怪癖。我注意到在显示内容时,ScrollViewer 实际上正在加载、卸载和再次加载。

这意味着我不能只在 IsEnabledChanged 方法中连接事件并在 target_Unloaded 事件处理程序中解除它们,因为它们会立即解除。相反,我不得不将它们连接到 Loaded 事件的处理程序中,而该事件又永远不会被解除。

这意味着那里存在某种“内存泄漏”,但这是我准备忍受的。

关于c# - 使用 ScrollViewer 单击并拖动滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14781005/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com