I'm trying to make a custom WPF control where a TranslateTransform is applied based on two doubles (TranslateX, TranslateY) that are data bound to the TranslateTransform, this works perfectly well when using buttons or scrollbars to manipulate the two doubles, but I'd like the users to drag inside the custom control to translate the controls inside it.
To do this I've added a PreviewMouseDown, Up and Move handler inside my custom control. (As I understand it, I should always receive the 'preview' events because they tunnel from the bottom down instead of bubbling up).
//Inside the constructor of the custom control
Mouse.AddPreviewMouseDownHandler(this, new MouseButtonEventHandler(MouseDown));
Mouse.AddPreviewMouseUpHandler(this, new MouseButtonEventHandler(MouseUp));
Mouse.AddPreviewMouseMoveHandler(this, new MouseEventHandler(MouseMoved));
The events are handled by the following methods:
private void OnMouseDown(object o, MouseEventArgs args)
{
Mouse.Capture(this, C开发者_JAVA技巧aptureMode.Element);
prevMousePosition = args.GetPosition(this);
}
private void OnMouseUp(object o, MouseEventArgs args)
{
Mouse.Capture(this, CaptureMode.None);
}
private void OnMouseMoved(object o, MouseEventArgs args)
{
if (args.LeftButton == MouseButtonState.Pressed)
{
Vector change = prevMousePosition - args.GetPosition(this);
TranslateX += change.X;
TranslateY += change.Y;
prevMousePosition = args.GetPosition(this);
}
}
However the OnMouseMoved method is only called when I frantically move the mouse around and not if I slowly move it (which most people would do when dragging). Also (understandably) the event totally stops firing when I get outside of the custom control while users might want to keep dragging further without having to reposition their mouse.
So my question is: how do I capture the mouse position and it's move events in such a way that users can smoothly drag inside the custom control, and can keep dragging even if their dragging caused the mouse to get outside the custom control?
(Small note: I'm still using .NET 3.5)
After searching for "google maps like dragging in WPF" I found another SO question which answered my qeustion perfectly by providing a virtualized WPF canvas that can scroll and zoom, now I can dissect the code to see how it should be done.
For now I'll share the link: http://blogs.msdn.com/b/jgoldb/archive/2008/03/08/performant-virtualized-wpf-canvas.aspx
Virtualized WPF Canvas
As you may already know WPF has a built-in virtualizing panel called VirtualizingStackPanel that supports UI virtualization and lays out its elements like StackPanel.
The WPF ListBox & ListView controls use this panel by default. Other containers controls such as Canvas do not have virtualization support in .Net 3.0 & 3.5.
Chris Lovett from Microsoft now wrote a great sample that shows how you can also virtualize a Canvas container control so it can efficiently host and scroll thousands of WPF elements without consuming huge amount of memory.
The provided down-loadable ZIP has a white paper and the code.
VirtualCanvas.zip
(Sorry, I should've searched better, but I didn't think of adding search terms of similar software that has this feature).
精彩评论