zoukankan      html  css  js  c++  java
  • WPF自定义控件一:StackPanel 控件轮播

    实现效果

    带定时器的轮播图

    using引用

    using System.Windows;


    using System.Windows.Controls;


    using System.Windows.Markup;


    using System.Windows.Media;


    using System.Windows.Media.Animation;


    using System.Windows.Threading;

    自定义Control

     /// <summary>
        /// 轮播控件
        /// </summary>
        [ContentProperty(nameof(Children))]
        public class CarRoundPlay:Control
        {
    
            private StackPanel stackPanel;
    
            private DispatcherTimer _DtAutoPlay;
            static CarRoundPlay()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(CarRoundPlay), new FrameworkPropertyMetadata(typeof(CarRoundPlay)));
            }
            /// <summary>
            /// 构造方法
            /// </summary>
            public CarRoundPlay()
            {
                Children = new ObservableCollection<UIElement>();
                Loaded += CarRoundPlay_Load;
                SizeChanged += CarRoundPlay_Changed;
            }
    
            /// <summary>
            /// 大小发生改变时
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void CarRoundPlay_Changed(object sender, SizeChangedEventArgs e)
            {
                foreach (FrameworkElement child in Children)
                {
                    child.Width = ActualWidth;
                    child.Height = ActualHeight;
                }
            }
    
            /// <summary>
            /// 控件初始化
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void CarRoundPlay_Load(object sender, RoutedEventArgs e)
            {
                //判断子集合是否为空
                if (Children == null)
                    return;
                //便利子集布局并将当前容器宽高赋予子集布局控件
                foreach (FrameworkElement child in Children)
                {
                    child.Width = ActualWidth;
                    child.Height = ActualHeight;
                }
            }
    
    
            public override void OnApplyTemplate()
            {
                base.OnApplyTemplate();
                //获取当前显示布局控件
                stackPanel = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this, 0), 0) as StackPanel;
            }
            /// <summary>
            /// 图片大小发生改变时
            /// </summary>
            /// <param name="d"></param>
            /// <param name="e"></param>
            private static void OnIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var carousel = d as CarRoundPlay;
                if (!carousel.IsLoaded)
                    return;
                var targetIndex = 0;
                if (!carousel.Recyclable)
                    targetIndex = carousel.Index > (carousel.Children.Count - 1) ? carousel.Children.Count - 1 : (carousel.Index < 0 ? 0 : carousel.Index);
                else
                    targetIndex = carousel.Index > (carousel.Children.Count - 1) ? 0 : (carousel.Index < 0 ? carousel.Children.Count - 1 : carousel.Index);
    
                if (targetIndex != carousel.Index)
                {
                    carousel.Index = targetIndex;
                    return;
                }
                carousel.ResetAutoPlayTimer();
                ///判断控件布局触发动画
                if (carousel.Orientation == Orientation.Vertical)
                {
                    carousel.stackPanel.BeginAnimation(StackPanel.MarginProperty, new ThicknessAnimation()
                    {
                        To = new Thickness(0, -1 * carousel.ActualHeight * carousel.Index, 0, 0),
                        Duration = carousel.AnimateDuration,
                        EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut }
                    });
                }
                else
                {
                    carousel.stackPanel.BeginAnimation(StackPanel.MarginProperty, new ThicknessAnimation()
                    {
                        To = new Thickness(-1 * carousel.ActualWidth * carousel.Index, 0, 0, 0),
                        Duration = carousel.AnimateDuration,
                        EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut }
                    });
                }
                carousel.RaiseIndexChanged(targetIndex);
            }
            private static void OnAutoPlayIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var carousel = d as CarRoundPlay;
                carousel.RestartAutoPlayTimer();
            }
            /// <summary>
            /// 定时切换
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void DispatcherTimerAutoPlay_Tick(object sender, EventArgs e)
            {
                Index++;
            }
            public T FindFirstVisualChild<T>(DependencyObject obj, string childName) where T : DependencyObject
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                    if (child != null && child is T && child.GetValue(NameProperty).ToString() == childName)
                    {
                        return (T)child;
                    }
                    else
                    {
                        T childOfChild = FindFirstVisualChild<T>(child, childName);
                        if (childOfChild != null)
                        {
                            return childOfChild;
                        }
                    }
                }
                return null;
            }
    
            #region 公共
    
            /// <summary>
            /// 子集合控件
            /// </summary>
            public ObservableCollection<UIElement> Children
            {
                get { return (ObservableCollection<UIElement>)GetValue(ChildrenProperty); }
                private set { SetValue(ChildrenProperty, value); }
            }
    
            public static readonly DependencyProperty ChildrenProperty =
                DependencyProperty.Register("Children", typeof(ObservableCollection<UIElement>), typeof(CarRoundPlay));
    
    
            /// <summary>
            /// 布局方向
            /// </summary>
            public Orientation  Orientation
            {
                get { return (Orientation)GetValue( OrientationProperty); }
                set { SetValue( OrientationProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for  Orientation.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty  OrientationProperty =
                DependencyProperty.Register("Orientation", typeof(Orientation), typeof(CarRoundPlay), new PropertyMetadata(Orientation.Horizontal));
    
    
            /// <summary>
            /// 
            /// </summary>
            public int Index
            {
                get { return (int)GetValue(IndexProperty); }
                set { SetValue(IndexProperty, value); }
            }
    
            public static readonly DependencyProperty IndexProperty =
                DependencyProperty.Register("Index", typeof(int), typeof(CarRoundPlay), new PropertyMetadata(0, OnIndexChanged));
    
            /// <summary>
            /// 动画耗时
            /// </summary>
            public TimeSpan AnimateDuration
            {
                get { return (TimeSpan)GetValue(AnimateDurationProperty); }
                set { SetValue(AnimateDurationProperty, value); }
            }
    
            public static readonly DependencyProperty AnimateDurationProperty =
                DependencyProperty.Register("AnimateDuration", typeof(TimeSpan), typeof(CarRoundPlay), new PropertyMetadata(TimeSpan.FromSeconds(0.5)));
    
            /// <summary>
            /// 设置获取
            /// </summary>
            public bool Recyclable
            {
                get { return (bool)GetValue(RecyclableProperty); }
                set { SetValue(RecyclableProperty, value); }
            }
    
            public static readonly DependencyProperty RecyclableProperty =
                DependencyProperty.Register("Recyclable", typeof(bool), typeof(CarRoundPlay), new PropertyMetadata(false));
    
            /// <summary>
            /// 自动动画
            /// </summary>
            public TimeSpan AutoPlayInterval
            {
                get { return (TimeSpan)GetValue(AutoPlayIntervalProperty); }
                set { SetValue(AutoPlayIntervalProperty, value); }
            }
    
            public static readonly DependencyProperty AutoPlayIntervalProperty =
                DependencyProperty.Register("AutoPlayInterval", typeof(TimeSpan), typeof(CarRoundPlay), new PropertyMetadata(OnAutoPlayIntervalChanged));
    
    
        
            #endregion
    
    
    
            #region RoutedEvent(路由事件)
            /// <summary>
            /// 轮播index
            /// </summary>
            public static readonly RoutedEvent IndexChangedEvent = EventManager.RegisterRoutedEvent("IndexChanged", RoutingStrategy.Bubble, typeof(IndexChangedEventHandler), typeof(CarRoundPlay));
            public event IndexChangedEventHandler IndexChanged
            {
                add { AddHandler(IndexChangedEvent, value); }
                remove { RemoveHandler(IndexChangedEvent, value); }
            }
            void RaiseIndexChanged(int newValue)
            {
                var arg = new IndexChangedEventArgs(newValue, IndexChangedEvent);
                RaiseEvent(arg);
    
            }
    
    
            #endregion
    
            #region Function
            private void RestartAutoPlayTimer()
            {
                if (_DtAutoPlay != null)
                {
                    _DtAutoPlay.Stop();
                }
                if (AutoPlayInterval.TotalSeconds != 0)
                {
                    _DtAutoPlay = new DispatcherTimer()
                    {
                        Interval = AutoPlayInterval,
                    };
                    _DtAutoPlay.Tick += DispatcherTimerAutoPlay_Tick;
                    _DtAutoPlay.Start();
                }
            }
    
        
    
            private void ResetAutoPlayTimer()
            {
                if (_DtAutoPlay != null)
                {
                    _DtAutoPlay.Stop();
                    _DtAutoPlay.Start();
                }
            }
            #endregion
    
        }
       public class IndexChangedEventArgs : RoutedEventArgs
        {
            public IndexChangedEventArgs(int currentIndex, RoutedEvent routedEvent) : base(routedEvent)
            {
                CurrentIndex = currentIndex;
            }
    
            public int CurrentIndex { get; set; }
        }
    
        public delegate void IndexChangedEventHandler(object sender, IndexChangedEventArgs e);

    样式

        <Style TargetType="{x:Type Modules:CarRoundPlay}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Modules:CarRoundPlay}">
                        <Grid Background="{TemplateBinding Background}"
                              ClipToBounds="True">
                            <StackPanel Orientation="{TemplateBinding Orientation}">
                                <ItemsControl ItemsSource="{TemplateBinding Children}"
                                              VerticalAlignment="Stretch"
                                              HorizontalAlignment="Stretch">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <StackPanel Orientation="{Binding Orientation,RelativeSource={RelativeSource AncestorType=Modules:CarRoundPlay}}" />
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <ContentControl  Content="{Binding}" />
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
                            </StackPanel>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    调用方法

    方法一

    xmlns:Zt="clr-namespace:RoundPlay.Modules"
    
      <Grid>
                <Zt:CarRoundPlay 
                           BorderBrush="LightGray"
                                     BorderThickness="1
    Recyclable="True" AutoPlayInterval="0:0:1"
    Height="300" Index="3" Width="300"> <Grid Background="#F15D26"> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" Text="Page1/44" /> </Grid> <Grid Background="Beige"> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" Text="Page1/44" /> </Grid> <Grid Background="Blue"> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" Text="Page1/44" /> </Grid> </Zt:CarRoundPlay> </Grid>

     方法二

                SolidColorBrush[] brushes = new SolidColorBrush[4] { Brushes.White, Brushes.Red, Brushes.Green, Brushes.Yellow };
                Random rnd = new Random();
                MainViewModel viewmodel = (this.DataContext as MainViewModel);
                for (int i = 0; i < viewmodel.ComWorldLists.Count; i++)
                {
                    Grid grid = new Grid();
                    int random = rnd.Next(0, brushes.Length - 1);
                    grid.Background = brushes[random];
                    TextBlock text = new TextBlock() { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, FontSize = 24, FontWeight = FontWeights.Bold };
                    text.SetBinding(TextBlock.TextProperty, new Binding($"ComWorldLists[{i}].Name"));
                    grid.Children.Add(text);
                    Caruousel.Children.Add(grid);
                }

     显示效果

  • 相关阅读:
    useCallback优化React Hooks程序性能
    useMemo优化React Hooks程序性能,解决子组件重复执行问题
    使用 useReducer 和 useCallback 解决 useEffect 依赖诚实与方法内置&外置问题
    createContext 和 useContext 结合使用实现方法共享(React Hook跨组件透传上下文与性能优化)
    浅谈开发变量作用域---小坑
    优雅的在React项目中使用Redux
    浅谈react无状态组件(哑组件)和有状态组件(智能组件)的区别
    浅谈react-router和react-router-dom、react-router-native的区别
    windows系列CMD替换品Terminal控制台推荐——ConsoleZ
    struts——文件上传
  • 原文地址:https://www.cnblogs.com/zt199510/p/14023208.html
Copyright © 2011-2022 走看看