WPF 縮略圖功能 小面板 移動可改變滾動條

資源下載連接

https://download.csdn.net/download/sinat_30224769/12362527

 

獲取背景板

        public VisualBrush GetVisualBrush()
        {
            VisualBrush brush = new VisualBrush();
            brush.Stretch = Stretch.Fill;
            brush.Visual = myViewbox;
            brush.Opacity = 0.75;
            return brush;
        }


ZoomBox.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ZoomBox
{
    /// <summary>
    /// Interaction logic for ZoomBoxControl.xaml
    /// </summary>
    public partial class ZoomBoxControl : UserControl
    {
        public ZoomBoxControl()
        {
            InitializeComponent();
        }

        public enum Orientation
        {
            Horizontal,
            Vertical
        }

        public class ZoomArea
        {
            public Size ScreenSize { get; set; }
            /// <summary>
            /// 畫布大小 這裏目前展示的是最大節點位置的大小
            /// </summary>
            public Size CanvasSize { get; set; }
            //public Size ViewSize { get; set; }
        }

        /// <summary>
        /// 通知界面刷新
        /// </summary>
        public event Action<Orientation, double> OffsetChangedEventHandel;
        /// <summary>
        /// 獲取縮略圖背景
        /// </summary>
        public event Func<VisualBrush> GetCanvasBrushEventHandel;
        /// <summary>
        /// 獲取縮略圖範圍
        /// </summary>
        public event Func<ZoomArea> GetNodeMaxAreaEventHandel;

        /// <summary>
        /// 保留尺寸方便調用
        /// </summary>
        public Size MainCanvasSize
        {
            get { return (Size)GetValue(MainCanvasSizeProperty); }
            set { SetValue(MainCanvasSizeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MainCanvasSize.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MainCanvasSizeProperty =
            DependencyProperty.Register("MainCanvasSize", typeof(Size), typeof(ZoomBoxControl), new PropertyMetadata(new Size(200, 100)));

        public bool IsExpanded
        {
            get { return (bool)GetValue(IsExpandedProperty); }
            set { SetValue(IsExpandedProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsExpanded.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsExpandedProperty =
            DependencyProperty.Register("IsExpanded", typeof(bool), typeof(ZoomBoxControl), new PropertyMetadata(false));


        /// <summary>
        /// 更新縮略圖範圍
        /// </summary>
        /// <param name="zoomArea"></param>
        public void UpdateBackground(ZoomArea zoomArea)
        {
            if (zoomArea == null)
            {
                return;
            }

            //那一邊長哪一邊就直接展示200的長度
            double max = System.Math.Max(zoomArea.CanvasSize.Width, zoomArea.CanvasSize.Height);
            double min = System.Math.Min(zoomArea.CanvasSize.Width, zoomArea.CanvasSize.Height);
            double rate = max / min;
            if (rate >= 4)
            {
                zoomArea.CanvasSize = new Size(max, max);
            }
            this.MainCanvasSize = zoomArea.CanvasSize;



            if (zoomArea.CanvasSize.Width > zoomArea.CanvasSize.Height)
            {
                rate = this.MainCanvasSize.Height / this.MainCanvasSize.Width;
                ZoomBoxCanvas.Width = this.Width;
                ZoomBoxCanvas.Height = this.Width * rate;

                ZoomBackground.Height = ZoomBoxCanvas.Height;
                ZoomBackground.Width = ZoomBoxCanvas.Width;
            }
            else
            {
                rate = this.MainCanvasSize.Width / this.MainCanvasSize.Height;
                ZoomBoxCanvas.Height = this.Height;
                ZoomBoxCanvas.Width = this.Height * rate;

                ZoomBackground.Height = ZoomBoxCanvas.Height;
                ZoomBackground.Width = ZoomBoxCanvas.Width;
            }

            double scRateWidth = zoomArea.ScreenSize.Width / zoomArea.CanvasSize.Width;
            double scRateHeight = zoomArea.ScreenSize.Height / zoomArea.CanvasSize.Height;

            if (scRateWidth >= 1)
            {
                //說明屏幕展示的下 那麼在水平方向上 滑塊不可移動 應該等於畫布大小
                ZoomThumb.Width = ZoomBoxCanvas.Width;
            }
            else
            {
                var newWidth = scRateWidth * ZoomBoxCanvas.Width;
                if (newWidth < 40)
                {
                    newWidth = 40;
                }
                ZoomThumb.Width = newWidth;
            }

            if (scRateHeight >= 1)
            {
                //說明屏幕展示的下 那麼在垂直方向上 滑塊不可移動 應該等於畫布大小
                ZoomThumb.Height = ZoomBoxCanvas.Height;
            }
            else
            {
                var newHeight = scRateHeight * ZoomBoxCanvas.Height;
                if (newHeight < 40)
                {
                    newHeight = 40;
                }
                ZoomThumb.Height = newHeight;
            }


        }

        /// <summary>
        /// 更新滑塊位置
        /// </summary>
        /// <param name="offsetX"></param>
        /// <param name="offsetY"></param>
        public void ScrollChanged(double offsetX, double offsetY)
        {

            double offsetRateX = this.MainCanvasSize.Width / (this.ZoomBoxCanvas.Width - this.ZoomThumb.Width);
            double offsetRateY = this.MainCanvasSize.Height / (this.ZoomBoxCanvas.Height - this.ZoomThumb.Height);
            Canvas.SetLeft(ZoomThumb, offsetX / offsetRateX);
            Canvas.SetTop(ZoomThumb, offsetY / offsetRateY);
        }

        /// <summary>
        /// 拖拽滑塊
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ZoomThumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
        {
            //var ZoomThumb = sender as Thumb;
            Point ptChange = ZoomThumb.RenderTransform.Transform(new Point(e.HorizontalChange, e.VerticalChange));
            double left = Canvas.GetLeft(ZoomThumb);
            double top = Canvas.GetTop(ZoomThumb);

            double offsetX = 0;
            double offsetY = 0;

            double offsetRateX = this.MainCanvasSize.Width / (this.ZoomBoxCanvas.Width - this.ZoomThumb.Width);
            double offsetRateY = this.MainCanvasSize.Height / (this.ZoomBoxCanvas.Height - this.ZoomThumb.Height);

            double minLeft = 0;
            double maxLeft = this.ZoomBoxCanvas.Width - ZoomThumb.Width;
            double minTop = 0;
            double maxTop = this.ZoomBoxCanvas.Height - ZoomThumb.Height;


            Console.WriteLine(left + "," + top + "," + e.HorizontalChange + "," + e.VerticalChange);
            if (e.HorizontalChange <= 0)
            {
                if (left <= minLeft)
                {
                    offsetX = minLeft;
                }
                else
                {
                    offsetX = left + ptChange.X;
                }
            }
            else if (e.HorizontalChange >= 0)
            {
                if (left >= maxLeft)
                {
                    offsetX = maxLeft;
                }
                else
                {
                    offsetX = left + ptChange.X;
                }
            }
            else
            {
                offsetX = left + ptChange.X;
            }
            Canvas.SetLeft(ZoomThumb, offsetX);
            //scroll.ScrollToHorizontalOffset(offsetX * offsetRate);
            OffsetChangedEventHandel?.Invoke(Orientation.Horizontal, offsetX * offsetRateX);
            if (e.VerticalChange <= 0)
            {
                if (top <= minTop)
                {
                    offsetY = minTop;
                }
                else
                {
                    offsetY = top + ptChange.Y;
                }
            }
            else if (e.VerticalChange >= 0)
            {
                if (top >= maxTop)
                {
                    offsetY = maxTop;
                }
                else
                {
                    offsetY = top + ptChange.Y;
                }
            }
            else
            {
                offsetY = top + ptChange.Y;
            }
            Canvas.SetTop(ZoomThumb, offsetY);
            //scroll.ScrollToVerticalOffset(offsetY * offsetRate);
            OffsetChangedEventHandel?.Invoke(Orientation.Vertical, offsetY * offsetRateY);
            //Console.WriteLine($"left:{scroll.ContentHorizontalOffset} top:{scroll.ContentVerticalOffset}  OffsetX:{scroll.HorizontalOffset} OffsetY:{scroll.VerticalOffset}");
        }

        private void Expand_Click(object sender, RoutedEventArgs e)
        {
            IsExpanded = !IsExpanded;

            if (IsExpanded && GetNodeMaxAreaEventHandel != null)
            {
                var zoomSize = GetNodeMaxAreaEventHandel.Invoke();
                UpdateBackground(zoomSize);
                this.Dispatcher.InvokeAsync(() =>
                {
                    ZoomBackground.Background = GetCanvasBrushEventHandel?.Invoke();
                });
            }
        }


        //調用的位置 在滾動條變動的時候要發起通知
        //private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        //{
        //    var xx = scroll;
        //    Console.WriteLine($"left:{scroll.ContentHorizontalOffset} top:{scroll.ContentVerticalOffset}  OffsetX:{scroll.HorizontalOffset} OffsetY:{scroll.VerticalOffset}");
        //}

    }
}

ZoomBox.xml

<UserControl x:Class="ZoomBox.ZoomBoxControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ZoomBox"
             mc:Ignorable="d" x:Name="uc"
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <SolidColorBrush x:Key="ThemColour" Color="LightGreen"/>
        <local:BooleanToVisibility x:Key="BooleanToVisibility" />
        <local:BooleanToReverseVisibility x:Key="BooleanToReverseVisibility" />
    </UserControl.Resources>
    <Grid>
        <Grid Background="#4CFFFFFF"  Visibility="{Binding IsExpanded,ElementName=uc,Converter={StaticResource BooleanToVisibility}}">
            <Border BorderThickness="1" BorderBrush="{StaticResource ThemColour}" d:IsHidden="True"/>
            <!--<Border BorderThickness="1" BorderBrush="#FFFBA90D" d:IsHidden="True"/>-->
            <Canvas Name="ZoomBoxCanvas"  Width="800" Height="100">
                <!--<Image Opacity="1" x:Name="ZoomBackground" Stretch="UniformToFill" Width="{Binding Width,ElementName=ZoomBoxCanvas}" Height="{Binding Height,ElementName=ZoomBoxCanvas}"/>-->
                <Border BorderThickness="1" BorderBrush="{StaticResource ThemColour}" Width="{Binding Width,ElementName=ZoomBoxCanvas}" Height="{Binding Height,ElementName=ZoomBoxCanvas}"/>
                <Grid x:Name="ZoomBackground" />
                <Grid x:Name="ZoomThumb" Canvas.Left="0" Canvas.Top="0"  Height="38" Width="50"   Background="{StaticResource ThemColour}" >
                    <Thumb  Opacity="0.1" Background="Transparent"  DragDelta="ZoomThumb_DragDelta"  HorizontalAlignment="Left" Height="{Binding Height,ElementName=ZoomThumb}" Width="{Binding Width,ElementName=ZoomThumb}"  VerticalAlignment="Top"  Foreground="{x:Null}" BorderBrush="Black"/>
                </Grid>
            </Canvas>

        </Grid>
        <RadioButton  Click="Expand_Click" Visibility="{Binding IsExpanded,ElementName=uc,Converter={StaticResource BooleanToReverseVisibility }}" HorizontalAlignment="Right" Height="56" Width="22" Margin="0" VerticalAlignment="Bottom">
            <RadioButton.Template>
                <ControlTemplate>
                    <Grid  Background="White">
                        <Border BorderThickness="1" BorderBrush="{StaticResource ThemColour}"/>
                        <TextBlock Text="縮略圖" Foreground="{StaticResource ThemColour}" VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap" FontSize="14"/>
                    </Grid>
                </ControlTemplate>
            </RadioButton.Template>
        </RadioButton>
        <RadioButton Click="Expand_Click"  Visibility="{Binding IsExpanded,ElementName=uc,Converter={StaticResource BooleanToVisibility}}" HorizontalAlignment="Right" Height="22" Width="22" Margin="0" VerticalAlignment="Bottom" MinHeight="0">
            <RadioButton.Template>
                <ControlTemplate>
                    <Grid  Background="White">
                        <Border BorderThickness="1" BorderBrush="{StaticResource ThemColour}"/>
                        <TextBlock Text=">>" Foreground="{StaticResource ThemColour}" VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap" FontSize="14"/>
                    </Grid>
                </ControlTemplate>
            </RadioButton.Template>
        </RadioButton>
    </Grid>
</UserControl>

Main.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ZoomBox
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            zoomBox.ScrollChanged(scrollViewer.HorizontalOffset, scrollViewer.VerticalOffset);
        }

        private void ZoomBoxControl_OffsetChangedEventHandel(ZoomBoxControl.Orientation arg1, double arg2)
        {
            if (double.IsNaN(arg2))
            {
                return;
            }

            if (arg1 == ZoomBoxControl.Orientation.Horizontal)
            {
                scrollViewer.ScrollToHorizontalOffset(arg2);
            }
            else
            {
                scrollViewer.ScrollToVerticalOffset(arg2);
            }
        }

        private ZoomBoxControl.ZoomArea zoomBox_GetNodeMaxAreaEventHandel()
        {
            ZoomBoxControl.ZoomArea zoomArea = new ZoomBoxControl.ZoomArea();
            zoomArea.ScreenSize = scrollViewer.RenderSize;
            zoomArea.CanvasSize = VeryBigCanvas.RenderSize;
            return zoomArea;
        }
        private VisualBrush zoomBox_GetCanvasBrushEventHandel()
        {
            return GetVisualBrush();
        }
        public VisualBrush GetVisualBrush()
        {
            VisualBrush brush = new VisualBrush();
            brush.Stretch = Stretch.Fill;
            brush.Visual = VeryBigCanvas;
            brush.Opacity = 0.75;
            return brush;
        }
    }
}

Main.xml

 

<Window x:Class="ZoomBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ZoomBox"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ScrollViewer x:Name="scrollViewer" ScrollChanged="ScrollViewer_ScrollChanged" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
            <Canvas x:Name="VeryBigCanvas" HorizontalAlignment="Left" Height="4320" Width="7680"  VerticalAlignment="Top" >
                <Canvas.Background>
                    <ImageBrush ImageSource="lol娑娜大胸白絲4k壁紙_彼岸圖網.jpg"/>
                </Canvas.Background>
            </Canvas>
        </ScrollViewer>

        <local:ZoomBoxControl x:Name="zoomBox" OffsetChangedEventHandel="ZoomBoxControl_OffsetChangedEventHandel" GetNodeMaxAreaEventHandel="zoomBox_GetNodeMaxAreaEventHandel" GetCanvasBrushEventHandel="zoomBox_GetCanvasBrushEventHandel"  Width="200" Height="200" Margin="0,0,20,20" VerticalAlignment="Bottom" HorizontalAlignment="Right" />
    </Grid>
</Window>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章