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);
}
显示效果

WPF自定义控件一:StackPanel 控件轮播的更多相关文章
- WPF自定义控件二:Border控件与TextBlock控件轮播动画
需求:实现Border轮播动画与TextBlock动画 XAML代码如下: <Window.Resources> <Storyboard x:Key="OnLoaded1& ...
- WPF自定义控件之图片控件 AsyncImage
AsyncImage 是一个封装完善,使用简便,功能齐全的WPF图片控件,比直接使用Image相对来说更加方便,但它的内部仍然使用Image承载图像,只不过在其基础上进行了一次完善成熟的封装 Asyn ...
- WPF后台设置xaml控件的样式System.Windows.Style
WPF后台设置xaml控件的样式System.Windows.Style 摘-自 :感谢 作者: IT小兵 http://3w.suchso.com/projecteac-tual/wpf-zhi ...
- 在WPF中使用WinForm控件方法
1. 首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,System.Windows.Forms.dll. 2. 在要使用WinForm控 ...
- WPF Step By Step 控件介绍
WPF Step By Step 控件介绍 回顾 上一篇,我们主要讨论了WPF的几个重点的基本知识的介绍,本篇,我们将会简单的介绍几个基本控件的简单用法,本文会举几个项目中的具体的例子,结合这些 例子 ...
- 背水一战 Windows 10 (79) - 自定义控件: Layout 系统, 控件模板, 事件处理
[源码下载] 背水一战 Windows 10 (79) - 自定义控件: Layout 系统, 控件模板, 事件处理 作者:webabcd 介绍背水一战 Windows 10 之 控件(自定义控件) ...
- Wpf使用Winform控件后Wpf元素被Winform控件遮盖问题的解决
有人会说不建议Wpf中使用Winform控件,有人会说建议使用Winform控件在Wpf下的替代方案,然而在实际工作中由于项目的特殊需求,考虑到时间.成本等因素,往往难免会碰到在WPF中使用Winfr ...
- WPF自定义选择年月控件详解
本文实例为大家分享了WPF自定义选择年月控件的具体代码,供大家参考,具体内容如下 封装了一个选择年月的控件,XAML代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...
- WPF学习- AllowDrop 用户控件启用拖放功能
知识点: 创建自定义用户控件(UserControl) 使用户控件成为拖动源 使用户控件成为放置目标 使面板能够接收从用户控件放置的数据 创建项目: 1.新建WPF项目(Wpf-AllowDrop) ...
随机推荐
- CentOS-Docker搭建VeryNginx
下载镜像 $ docker pull camil/verynginx $ cd /home GIT克隆(yum install git -y) $ git clone https://github.c ...
- robotframework使用过程中的一些总结
p.p1 { margin: 0; font: 20px "Helvetica Neue"; color: rgba(53, 53, 53, 1) } p.p2 { margin: ...
- Java多线程事务管理
今天要讨论的是"Java实现多线程单条数据事务管理",在此之前,顺便回顾一下实现多线程的几种方式 实现多线程的三种方式 一.继承Thread类 第一种方法是继承Thread类,重写 ...
- Java程序设计(2021春)——第二章课后题(选择题+编程题)答案与详解
Java程序设计(2021春)--第二章课后题(选择题+编程题)答案与详解 目录 Java程序设计(2021春)--第二章课后题(选择题+编程题)答案与详解 第二章选择题 2.1 面向对象方法的特性 ...
- git常用命令自己梳理总结
一.新建代码库 # git-init - 创建一个空的 Git 存储库或重新初始化一个现有的存储库 $ git init # 在本地新建一个repo,进入一个项目目录,执行git init,会初始化一 ...
- MySQL | Xtrabackup 安装
rpm方式安装 # xtrabackup 2.4.8 安装包 wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup- ...
- I-Identical Day[题解]
原题目地址(牛客) Identical Day 题目大意 给定一个长度为 \(n\) 的 \(01\) 串,对于每段长度为 \(l\) 的连续的 \(1\) ,其权值为 \(\frac{l\times ...
- shell脚本(2)-shell脚本语法
一.如何抒写shell脚本 1.shell脚本的命名 名字要有意义,不要以a.b.c.1.2.3这种方式命令,建议以sh结尾,在30个字节内,例如:check_memory.sh 2.shell脚本 ...
- 第 3 题:如何理解 HTML5 语义化?
什么是标签语义化? 提升代码可读性,便于团队开发和维护 为什么要标签语义化? 当网页去掉 CSS 样式时,页面能呈现出来清晰的结构 案例 不存在语义化 <div></div> ...
- JPA用法中字段起名规范
前两天在学习Springboot使用JPA 来操作数据库时,碰到一个问题,最终发现了JPA写法中表字段名称要写规范. 记录下来提醒自己. CityEntity是一个City的实体类. 1 @Table ...