WPF 可缩放ScrollView(方式二)
与方式一相比:
增加了缩放Maximun、Minimun和Value值,以及可供监听缩放变化的ValueChanged事件。
1 public class ScaleScrollView : ScrollViewer 2 { 3 readonly List<object> ValueChangedEvents = new List<object>(); 4 public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<double>), typeof(ScaleScrollView)); 5 /// <summary> 6 /// 通过监听此事件对内容进行缩放 7 /// </summary> 8 public event RoutedPropertyChangedEventHandler<double> ValueChanged 9 { 10 add => AddHandler(ValueChangedEvent, value); 11 remove => RemoveHandler(ValueChangedEvent, value); 12 } 13 14 #region Properties 15 16 17 public double Maximum 18 { 19 get { return (double)GetValue(MaximumProperty); } 20 set { SetValue(MaximumProperty, value); } 21 } 22 23 public static readonly DependencyProperty MaximumProperty = 24 DependencyProperty.Register("Maximum", typeof(double), typeof(ScaleScrollView), new PropertyMetadata(1200d)); 25 26 27 28 public double Minimum 29 { 30 get { return (double)GetValue(MinimumProperty); } 31 set { SetValue(MinimumProperty, value); } 32 } 33 34 public static readonly DependencyProperty MinimumProperty = 35 DependencyProperty.Register("Minimum", typeof(double), typeof(ScaleScrollView), new PropertyMetadata(1d)); 36 37 38 39 public double SmallChange 40 { 41 get { return (double)GetValue(SmallChangeProperty); } 42 set { SetValue(SmallChangeProperty, value); } 43 } 44 45 // Using a DependencyProperty as the backing store for SmallChange. This enables animation, styling, binding, etc... 46 public static readonly DependencyProperty SmallChangeProperty = 47 DependencyProperty.Register("SmallChange", typeof(double), typeof(ScaleScrollView), new PropertyMetadata(1d)); 48 49 50 51 public double Value 52 { 53 get { return (double)GetValue(ValueProperty); } 54 set { SetValue(ValueProperty, value); } 55 } 56 57 public static readonly DependencyProperty ValueProperty = 58 DependencyProperty.Register("Value", typeof(double), typeof(ScaleScrollView), 59 new FrameworkPropertyMetadata(100d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange, propertyChangedCallback: onValueConagend)); 60 61 private static void onValueConagend(DependencyObject d, DependencyPropertyChangedEventArgs e) 62 { 63 ScaleScrollView view = d as ScaleScrollView; 64 int ov = Convert.ToInt32(e.OldValue); 65 int nv = Convert.ToInt32(e.NewValue); 66 67 RoutedPropertyChangedEventArgs<double> args = new RoutedPropertyChangedEventArgs<double>(ov, nv); 68 args.RoutedEvent = ValueChangedEvent; 69 view.RaiseEvent(args); 70 71 if (args.Handled) return; 72 if (view.Content is FrameworkElement element) 73 { 74 double w = element.ActualWidth + element.ActualWidth * (nv - ov) / 100; 75 element.Width = w < 1.0 ? 1.0 : w; 76 double h = element.ActualHeight + element.ActualHeight * (nv - ov) / 100; 77 element.Height = h < 1.0 ? 1.0 : h; 78 } 79 80 } 81 82 83 #endregion 84 85 protected override void OnMouseWheel(MouseWheelEventArgs e) 86 { 87 if (e.Handled) { return; } 88 89 if (ScrollInfo != null) 90 { 91 //Shift+滚动:上下滚动 92 //Ctrl+滚动:左右滚动 93 //滚动:放大缩小 94 if (Keyboard.IsKeyDown(Key.LeftShift)) 95 { 96 if (e.Delta > 0) 97 ScrollInfo.MouseWheelUp(); 98 else 99 ScrollInfo.MouseWheelDown(); 100 } 101 else if (Keyboard.IsKeyDown(Key.LeftCtrl)) 102 { 103 if (e.Delta > 0) 104 ScrollInfo.LineLeft(); 105 else 106 ScrollInfo.MouseWheelRight(); 107 } 108 else 109 { 110 Value += e.Delta > 0 ? SmallChange : -SmallChange; 111 } 112 } 113 114 e.Handled = true; 115 } 116 }
示例:
1 <DockPanel> 2 <WrapPanel DockPanel.Dock="Bottom"> 3 <Slider Name="sliderScale" Minimum="1" Value="100" Maximum="1000" SmallChange="1" LargeChange="50" IsSnapToTickEnabled="True" Width="100"/> 4 <TextBlock Text="{Binding ElementName=sliderScale, Path=Value}" VerticalAlignment="Center"/> 5 </WrapPanel> 6 <controls:ScaleScrollView HorizontalScrollBarVisibility="Visible" Value="{Binding ElementName=sliderScale, Path=Value, Mode=TwoWay}"> 7 <Viewbox Name="viewbox"> 8 <Border Width="2000" Height="2000" Background="Orange"> 9 <Canvas> 10 <Rectangle Fill="Red" Width="1000" Height="1000"/> 11 </Canvas> 12 </Border> 13 </Viewbox> 14 </controls:ScaleScrollView> 15 </DockPanel>