X3

RedSky

导航

WPF 可缩放ScrollView(方式二)

方式一

增加了缩放Maximun、Minimun和Value值,以及可供监听缩放变化的ValueChanged事件。

public class ScaleScrollView : ScrollViewer
    {
        readonly List<object> ValueChangedEvents = new List<object>();
        public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<double>), typeof(ScaleScrollView));
        /// <summary>
        /// 通过监听此事件对内容进行缩放
        /// </summary>
        public event RoutedPropertyChangedEventHandler<double> ValueChanged
        {
            add => AddHandler(ValueChangedEvent, value);
            remove => RemoveHandler(ValueChangedEvent, value);
        }

        #region Properties


        public double Maximum
        {
            get { return (double)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }

        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(double), typeof(ScaleScrollView), new PropertyMetadata(1200d));



        public double Minimum
        {
            get { return (double)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }

        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register("Minimum", typeof(double), typeof(ScaleScrollView), new PropertyMetadata(1d));



        public double SmallChange
        {
            get { return (double)GetValue(SmallChangeProperty); }
            set { SetValue(SmallChangeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SmallChange.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SmallChangeProperty =
            DependencyProperty.Register("SmallChange", typeof(double), typeof(ScaleScrollView), new PropertyMetadata(1d));



        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(ScaleScrollView),
                new FrameworkPropertyMetadata(100d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange, propertyChangedCallback: onValueConagend));

        private static void onValueConagend(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ScaleScrollView view = d as ScaleScrollView;
            int ov = Convert.ToInt32(e.OldValue);
            int nv = Convert.ToInt32(e.NewValue);

            RoutedPropertyChangedEventArgs<double> args = new RoutedPropertyChangedEventArgs<double>(ov, nv);
            args.RoutedEvent = ValueChangedEvent;
            view.RaiseEvent(args);

            if (args.Handled) return;
            if (view.Content is FrameworkElement element)
            {
                double w = element.ActualWidth + element.ActualWidth * (nv - ov) / 100;
                element.Width = w < 1.0 ? 1.0 : w;
                double h = element.ActualHeight + element.ActualHeight * (nv - ov) / 100;
                element.Height = h < 1.0 ? 1.0 : h;
            }

        }


        #endregion

        protected override void OnMouseWheel(MouseWheelEventArgs e)
        {
            if (e.Handled) { return; }

            if (ScrollInfo != null)
            {
                //Shift+滚动:上下滚动
                //Ctrl+滚动:左右滚动
                //滚动:放大缩小
                if (Keyboard.IsKeyDown(Key.LeftShift))
                {
                    if (e.Delta > 0)
                        ScrollInfo.MouseWheelUp();
                    else
                        ScrollInfo.MouseWheelDown();
                }
                else if (Keyboard.IsKeyDown(Key.LeftCtrl))
                {
                    if (e.Delta > 0)
                        ScrollInfo.LineLeft();
                    else
                        ScrollInfo.MouseWheelRight();
                }
                else
                {
                    Value += e.Delta > 0 ? SmallChange : -SmallChange;
                }
            }

            e.Handled = true;
        }
    }

示例:

<DockPanel>
    <WrapPanel DockPanel.Dock="Bottom">
         <Slider Name="sliderScale" Minimum="1" Value="100" Maximum="1000" SmallChange="1" LargeChange="50" IsSnapToTickEnabled="True" Width="100"/>
             <TextBlock Text="{Binding ElementName=sliderScale, Path=Value}" VerticalAlignment="Center"/>
    </WrapPanel>
    <controls:ScaleScrollView HorizontalScrollBarVisibility="Visible" Value="{Binding ElementName=sliderScale, Path=Value, Mode=TwoWay}">
         <Viewbox Name="viewbox">
             <Border Width="2000" Height="2000" Background="Orange">
                  <Canvas>
                      <Rectangle Fill="Red" Width="1000" Height="1000"/>
                  </Canvas>
             </Border>
         </Viewbox>
    </controls:ScaleScrollView>
</DockPanel>

 

posted on 2022-03-22 15:47  HotSky  阅读(394)  评论(0编辑  收藏  举报