Unluckily there is no standard control to zoom, drag and scroll your content. My implementation is based on following tutorial. With this implementation you are able to zoom, drag and scroll arbitrary controls.
Showcase
ScrollDragZoomControl.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<UserControl x:Class="MinimalMonitoringClient.Controls.ScrollDragZoomControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="Transparent"> <UserControl.Template> <ControlTemplate TargetType="UserControl"> <ScrollViewer x:Name="scrollViewer" Loaded="scrollViewer_Loaded" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible"> <Grid Name="grid" RenderTransformOrigin="0.5,0.5"> <Grid.LayoutTransform> <TransformGroup> <ScaleTransform x:Name="scaleTransform" /> </TransformGroup> </Grid.LayoutTransform> <Viewbox> <!-- Present the actual stuff the user wants to display --> <ContentPresenter /> </Viewbox> </Grid> </ScrollViewer> </ControlTemplate> </UserControl.Template> </UserControl> |
ScrollDragZoomControl.xaml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace NAMESPACE { /// <summary> /// Interaktionslogik für ScrollDragZoomControl.xaml /// </summary> public partial class ScrollDragZoomControl : UserControl { private int zoomLevel = 1; private ScaleTransform scaleTransform; private ScrollViewer scrollViewer; private Grid grid; Point? lastCenterPositionOnTarget; Point? lastMousePositionOnTarget; Point? lastDragPoint; public ScrollDragZoomControl() { InitializeComponent(); } private void scrollViewer_Loaded(object sender, RoutedEventArgs e) { scaleTransform = (ScaleTransform)Template.FindName("scaleTransform", this); scrollViewer = (ScrollViewer)Template.FindName("scrollViewer", this); grid = (Grid)Template.FindName("grid", this); scrollViewer.ScrollChanged += OnScrollViewerScrollChanged; scrollViewer.MouseLeftButtonUp += OnMouseLeftButtonUp; scrollViewer.PreviewMouseLeftButtonUp += OnMouseLeftButtonUp; scrollViewer.PreviewMouseWheel += OnPreviewMouseWheel; scrollViewer.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown; scrollViewer.MouseMove += OnMouseMove; } void OnMouseMove(object sender, MouseEventArgs e) { if (lastDragPoint.HasValue) { Point posNow = e.GetPosition(scrollViewer); double dX = posNow.X - lastDragPoint.Value.X; double dY = posNow.Y - lastDragPoint.Value.Y; lastDragPoint = posNow; scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - dX); scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - dY); } } void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var mousePos = e.GetPosition(scrollViewer); if (mousePos.X <= scrollViewer.ViewportWidth && mousePos.Y < scrollViewer.ViewportHeight) //make sure we still can use the scrollbars { scrollViewer.Cursor = Cursors.SizeAll; lastDragPoint = mousePos; Mouse.Capture(scrollViewer); } } void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e) { lastMousePositionOnTarget = Mouse.GetPosition(grid); if (e.Delta > 0) zoomLevel++; else if (e.Delta < 0) zoomLevel--; zoomLevel = zoomLevel < 1 ? 1 : zoomLevel; scaleTransform.ScaleX = zoomLevel; scaleTransform.ScaleY = zoomLevel; var centerOfViewport = new Point(scrollViewer.ViewportWidth / 2, scrollViewer.ViewportHeight / 2); lastCenterPositionOnTarget = scrollViewer.TranslatePoint(centerOfViewport, grid); e.Handled = true; } void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { scrollViewer.Cursor = Cursors.Arrow; scrollViewer.ReleaseMouseCapture(); lastDragPoint = null; } void OnScrollViewerScrollChanged(object sender, ScrollChangedEventArgs e) { if (e.ExtentHeightChange != 0 || e.ExtentWidthChange != 0) { Point? targetBefore = null; Point? targetNow = null; if (!lastMousePositionOnTarget.HasValue) { if (lastCenterPositionOnTarget.HasValue) { var centerOfViewport = new Point(scrollViewer.ViewportWidth / 2, scrollViewer.ViewportHeight / 2); Point centerOfTargetNow = scrollViewer.TranslatePoint(centerOfViewport, grid); targetBefore = lastCenterPositionOnTarget; targetNow = centerOfTargetNow; } } else { targetBefore = lastMousePositionOnTarget; targetNow = Mouse.GetPosition(grid); lastMousePositionOnTarget = null; } if (targetBefore.HasValue) { double dXInTargetPixels = targetNow.Value.X - targetBefore.Value.X; double dYInTargetPixels = targetNow.Value.Y - targetBefore.Value.Y; double multiplicatorX = e.ExtentWidth / grid.Width; double multiplicatorY = e.ExtentHeight / grid.Height; double newOffsetX = scrollViewer.HorizontalOffset - dXInTargetPixels * multiplicatorX; double newOffsetY = scrollViewer.VerticalOffset - dYInTargetPixels * multiplicatorY; if (double.IsNaN(newOffsetX) || double.IsNaN(newOffsetY)) { return; } scrollViewer.ScrollToHorizontalOffset(newOffsetX); scrollViewer.ScrollToVerticalOffset(newOffsetY); } } } } } |
Usage
Add the “ScrollDragZoomControl” to your project and use it as follows:
1 2 3 |
<controls:ScrollDragZoomControl> <!-- Your Content to present --> </controls:ScrollDragZoomControl> |
Du musst angemeldet sein, um kommentieren zu können.