WPF轮播图实现方式(二)
生活随笔
收集整理的這篇文章主要介紹了
WPF轮播图实现方式(二)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?WPF開發者QQ群:?340500857? | 微信群 -> 進入公眾號主頁?加入組織
歡迎轉發、分享、點贊、在看,謝謝~。??
01
—
效果預覽
02
—
代碼如下
一、EmphasizerCarousel.cs 代碼如下
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Media.Animation; using WPFDevelopers.Controls.Helpers;namespace WPFDevelopers.Controls {[DefaultProperty("Children")][ContentProperty("Children")][Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)][TemplatePart(Name = Part_BackCanvasName, Type = typeof(Canvas))]public class EmphasizerCarousel : Control, IAddChild{static EmphasizerCarousel(){DefaultStyleKeyProperty.OverrideMetadata(typeof(EmphasizerCarousel), new FrameworkPropertyMetadata(typeof(EmphasizerCarousel)));}public EmphasizerCarousel(){Loaded += EmphasizerCarousel_Loaded;Unloaded += EmphasizerCarousel_Unloaded;SizeChanged += EmphasizerCarousel_SizeChanged;Children.CollectionChanged += OnItems_CollectionChanged;}[ReadOnly(true)]const string Part_BackCanvasName = "PART_BackCanvas";Canvas Part_BackCanvas = default;private const int _maxSimpleHeight = 320;private int _SimpleCount = 0;private FrameworkElement _DisplayItem = null;private double _SimpleTop = 0;private double _SimpleHeight = 0;private double _SimpleWidth = 0;//private double _SimpleOffset = 10;private double _DisplayHeight = 0;private double _DisplayWidth = 0;private double _DisplayOffset = 10d;private Dictionary<int, Point> _mapCanvasPoint = new Dictionary<int, Point>();private Dictionary<int, FrameworkElement> _mapUIwithIndex = new Dictionary<int, FrameworkElement>();private ObservableCollection<FrameworkElement> _Children = new ObservableCollection<FrameworkElement>();[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]public ObservableCollection<FrameworkElement> Children => _Children;private void OnItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e){if (e.Action == NotifyCollectionChangedAction.Add){foreach (var item in e.NewItems){if (item is FrameworkElement element){element.PreviewMouseLeftButtonDown += EmphasizerCarousel_MouseLeftButtonDown;element.RenderTransformOrigin = new Point(0.5, 0.5);element.RenderTransform = new TransformGroup{Children ={new ScaleTransform(),new SkewTransform(),new RotateTransform(),new TranslateTransform()}};}}}if (e.Action == NotifyCollectionChangedAction.Remove){foreach (var item in e.NewItems){if (item is FrameworkElement element)element.PreviewMouseLeftButtonDown -= EmphasizerCarousel_MouseLeftButtonDown;if (item == _DisplayItem)_DisplayItem = null;}}OnSizeChangedCallback();}#region overridepublic override void OnApplyTemplate(){base.OnApplyTemplate();Part_BackCanvas = GetTemplateChild(Part_BackCanvasName) as Canvas;if (Part_BackCanvas == null)throw new Exception("Some element is not in template!");}#endregionvoid IAddChild.AddChild(object value){throw new NotImplementedException();}void IAddChild.AddText(string text){throw new NotImplementedException();}private bool OnSizeChangedCallback(){if (Part_BackCanvas == null)return false;var vHeight = Part_BackCanvas.ActualHeight;var vWidth = Part_BackCanvas.ActualWidth;if (vHeight == Double.NaN || vWidth == Double.NaN)return false;if (vHeight == 0 || vWidth == 0)return false;Part_BackCanvas.Children.Clear();_mapUIwithIndex.Clear();_mapCanvasPoint.Clear();var vItemCount = Children.Count;if (vItemCount <= 0)return false;_SimpleCount = vItemCount - 1;if (_SimpleCount == 0){Children[0].Width = vWidth;Children[0].Height = vHeight;Part_BackCanvas.Children.Add(Children[0]);return true;}//計算并劃分顯示區域var vSimpleHeight = vHeight * 0.4;_SimpleHeight = vSimpleHeight;if (_SimpleHeight > _maxSimpleHeight)_SimpleHeight = _maxSimpleHeight;var vSimpleWidth = vWidth / _SimpleCount;_SimpleWidth = vSimpleWidth;_SimpleTop = vHeight - _SimpleHeight;_DisplayHeight = vHeight - _SimpleHeight;_DisplayHeight -= _DisplayOffset;_DisplayWidth = vWidth;if (_DisplayItem == null)_DisplayItem = Children[0];int nIndex = 0;int nPosIndex = 0;double Left = 0;foreach (var item in Children){Part_BackCanvas.Children.Add(item);item.Tag = nIndex;if (_DisplayItem == item){item.Width = _DisplayWidth;item.Height = _DisplayHeight;item.SetValue(Canvas.LeftProperty, 0d);item.SetValue(Canvas.TopProperty, 0d);}else{item.Width = _SimpleWidth;item.Height = _SimpleHeight;item.SetValue(Canvas.LeftProperty, Left);item.SetValue(Canvas.TopProperty, _SimpleTop);_mapCanvasPoint[nPosIndex] = new Point(Left, _SimpleTop);_mapUIwithIndex[nPosIndex] = item;Left += _SimpleWidth;++nPosIndex;}++nIndex;}return true;}private void EmphasizerCarousel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){if (sender == _DisplayItem)return;e.Handled = true;var vFrameWorker = sender as FrameworkElement;if (vFrameWorker == null)return;if (!int.TryParse(_DisplayItem.Tag.ToString(), out int nIndex))return;if (!int.TryParse(vFrameWorker.Tag.ToString(), out int nLeaveIndex))return;int offset = 500;var vLeft = (_DisplayWidth - _SimpleWidth) / 2d;var vTop = (_DisplayHeight - _SimpleHeight) / 2d;//一系列計算 計算得到當前展示頁要回到的Dock位置 //一系列計算 計算得到當前點擊頁要移除的Dock位置int nTargertIndex = nIndex;int nLeaveDockIndex = 0;foreach (var item in _mapUIwithIndex){if (!int.TryParse(item.Value.Tag.ToString(), out int nItemIndex))continue;if (nItemIndex == nLeaveIndex){nLeaveDockIndex = item.Key;_mapUIwithIndex[item.Key] = null;break;}}//如果目標位置Index是1那么他可以放在 0號位也可以放在1號位 主要是看他的前一個位置上的對象的Index是大還是小//判定 模擬演練 目標位置放入對象時 目標位置當前的對象時前移還是不動var vTargetFrame = _mapUIwithIndex.GetValueOrDefault(nTargertIndex);if (vTargetFrame != null){if (int.TryParse(vTargetFrame.Tag.ToString(), out int vTargetFrameIndex)){//先判定 后續動作是 左移還是右移bool? bLeft2Right = null;if (nTargertIndex > nLeaveDockIndex)bLeft2Right = false;else if (nTargertIndex < nLeaveDockIndex)bLeft2Right = true;if (bLeft2Right == true){if (vTargetFrameIndex < nIndex)nTargertIndex++;}if (bLeft2Right == false){if (vTargetFrameIndex > nIndex)nTargertIndex--;}}}if (nIndex >= _mapCanvasPoint.Count)nTargertIndex = _mapCanvasPoint.Count - 1;if (nIndex < 0)nTargertIndex = 0;Point point = _mapCanvasPoint.GetValueOrDefault(nTargertIndex);//定義動畫 Storyboard storyboard = new Storyboard{SpeedRatio = 2,};int nBegin = 250;if (nTargertIndex < nLeaveDockIndex){//全部右移for (int i = nLeaveDockIndex - 1; i >= nTargertIndex; --i){var vUI = _mapUIwithIndex.GetValueOrDefault(i);if (vUI == null)continue;var vPoint = _mapCanvasPoint.GetValueOrDefault(i + 1);DoubleAnimation animation = new DoubleAnimation(){To = vPoint.X,BeginTime = TimeSpan.FromMilliseconds(nBegin),Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, vUI);Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Left)"));storyboard.Children.Add(animation);if (_mapUIwithIndex.ContainsKey(i + 1))_mapUIwithIndex[i + 1] = vUI;_mapUIwithIndex[i] = null;//nBegin += nBegin;}}else if (nTargertIndex > nLeaveDockIndex){//全部左移for (int i = nLeaveDockIndex + 1; i <= nTargertIndex; ++i){var vUI = _mapUIwithIndex.GetValueOrDefault(i);if (vUI == null)continue;var vPoint = _mapCanvasPoint.GetValueOrDefault(i - 1);DoubleAnimation animation = new DoubleAnimation(){To = vPoint.X,BeginTime = TimeSpan.FromMilliseconds(nBegin),Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, vUI);Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Left)"));storyboard.Children.Add(animation);if (_mapUIwithIndex.ContainsKey(i - 1))_mapUIwithIndex[i - 1] = vUI;_mapUIwithIndex[i] = null;//nBegin += nBegin;}}if (_mapUIwithIndex.ContainsKey(nTargertIndex))_mapUIwithIndex[nTargertIndex] = _DisplayItem;//當前打開的界面 先縮放 位移 后 移到等待區{DoubleAnimation animation = new DoubleAnimation(){To = _SimpleWidth,Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, _DisplayItem);Storyboard.SetTargetProperty(animation, new PropertyPath("Width"));storyboard.Children.Add(animation);}{DoubleAnimation animation = new DoubleAnimation(){To = _SimpleHeight,Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, _DisplayItem);Storyboard.SetTargetProperty(animation, new PropertyPath("Height"));storyboard.Children.Add(animation);}{DoubleAnimation animation = new DoubleAnimation(){To = vLeft,Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, _DisplayItem);Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Left)"));storyboard.Children.Add(animation);}{DoubleAnimation animation = new DoubleAnimation(){To = vTop,Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, _DisplayItem);Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Top)"));storyboard.Children.Add(animation);}{DoubleAnimation animation = new DoubleAnimation(){To = point.X,BeginTime = TimeSpan.FromMilliseconds(offset),Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, _DisplayItem);Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Left)"));storyboard.Children.Add(animation);}{DoubleAnimation animation = new DoubleAnimation(){To = point.Y,BeginTime = TimeSpan.FromMilliseconds(offset),Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, _DisplayItem);Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Top)"));storyboard.Children.Add(animation);}//當前選中的界面 移動到目標位置 再放大位移{DoubleAnimation animation = new DoubleAnimation(){To = vLeft,BeginTime = TimeSpan.FromMilliseconds(offset),Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, vFrameWorker);Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Left)"));storyboard.Children.Add(animation);}{DoubleAnimation animation = new DoubleAnimation(){To = vTop,BeginTime = TimeSpan.FromMilliseconds(offset),Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, vFrameWorker);Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Top)"));storyboard.Children.Add(animation);}{DoubleAnimation animation = new DoubleAnimation(){To = _DisplayWidth,BeginTime = TimeSpan.FromMilliseconds(offset * 2),Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, vFrameWorker);Storyboard.SetTargetProperty(animation, new PropertyPath("Width"));storyboard.Children.Add(animation);}{DoubleAnimation animation = new DoubleAnimation(){To = _DisplayHeight,BeginTime = TimeSpan.FromMilliseconds(offset * 2),Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, vFrameWorker);Storyboard.SetTargetProperty(animation, new PropertyPath("Height"));storyboard.Children.Add(animation);}{DoubleAnimation animation = new DoubleAnimation(){To = 0,BeginTime = TimeSpan.FromMilliseconds(offset * 2),Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, vFrameWorker);Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Top)"));storyboard.Children.Add(animation);}{DoubleAnimation animation = new DoubleAnimation(){To = 0,BeginTime = TimeSpan.FromMilliseconds(offset * 2),Duration = new Duration(new TimeSpan(0, 0, 0, 0, offset)),EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut },};Storyboard.SetTarget(animation, vFrameWorker);Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Left)"));storyboard.Children.Add(animation);}_DisplayItem = vFrameWorker;storyboard.Begin(vFrameWorker);}private void EmphasizerCarousel_Loaded(object sender, RoutedEventArgs e){}private void EmphasizerCarousel_Unloaded(object sender, RoutedEventArgs e){}private void EmphasizerCarousel_SizeChanged(object sender, SizeChangedEventArgs e) => OnSizeChangedCallback();} }二、EmphasizerCarousel.xaml 代碼如下
三、CarouselExampleEx.xaml 代碼如下?
<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.CarouselExampleEx"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:WPFDevelopers.Samples.ExampleViews"xmlns:wpfdev="https://github.com/yanjinhuagood/WPFDevelopers"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"><Grid><wpfdev:EmphasizerCarousel><Image Source="pack://application:,,,/WPFDevelopers.Samples;component/Images/Craouse/0.jpg"/><Image Source="pack://application:,,,/WPFDevelopers.Samples;component/Images/Craouse/1.jpg"/><Image Source="pack://application:,,,/WPFDevelopers.Samples;component/Images/Craouse/2.jpg"/><Image Source="pack://application:,,,/WPFDevelopers.Samples;component/Images/Craouse/3.jpg"/><Image Source="pack://application:,,,/WPFDevelopers.Samples;component/Images/Craouse/4.jpg"/></wpfdev:EmphasizerCarousel></Grid> </UserControl>源碼地址
github:https://github.com/yanjinhuagood/WPFDevelopers.git
gitee:https://gitee.com/yanjinhua/WPFDevelopers.git
WPF開發者QQ群:?340500857?
Github:https://github.com/yanjinhuagood
版權:本作品采用「署名-非商業性使用-相同方式共享 4.0 國際」許可協議進行許可。
轉載請著名作者 出處 https://github.com/yanjinhuagood
總結
以上是生活随笔為你收集整理的WPF轮播图实现方式(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 那些35岁的程序员都去哪了
- 下一篇: 字符串池化,减少了三分之一的内存占用