WPF自定义控件一:StackPanel 控件轮播
阅读原文时间:2023年07月11日阅读:1

带定时器的轮播图

using System.Windows;

using System.Windows.Controls;

using System.Windows.Markup;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Threading;

///

/// 轮播控件 ///
[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"





方法二

        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);  
        }

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章