2
我想,讓點擊滾動使用拖放滾動ScrollViewer
(即點擊ScrollViewer
任何地方,上下拖動,這將相應地滾動)單擊並拖動使用的ScrollViewer
我有一個StackPanel
嵌套一個ScrollViewer
和我已經有滾動工作。我相信我在某個地方看到了答案,但我似乎無法再找到答案。
這隻能使用代碼來完成。
我想,讓點擊滾動使用拖放滾動ScrollViewer
(即點擊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事件的處理程序中,而該事件又永遠不會脫鉤。
這意味着在那裏存在某種「內存泄漏」,但這是我準備好要忍受的一種。
它導致內存泄漏,任何人都有更好的? – digz6666 2013-06-03 02:04:39