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) ...
随机推荐
- Java并发之ReentrantReadWriteLock源码解析(一)
ReentrantReadWriteLock 前情提要:在学习本章前,需要先了解笔者先前讲解过的ReentrantLock源码解析和Semaphore源码解析,这两章介绍了很多方法都是本章的铺垫.下面 ...
- Centos 6.5 GitLab安装配置搭建详细过程
GitLab搭建详细过程 一.前提 系统:Centos 6.5 软件版本:gitlab-7.8.4 Selinux:关闭 防火墙规则:先清空(搭建好了后续自己添加相关放行规则) 二.yum源配置和 ...
- Gerrit GitLab GitHub的几点不同
代码评审的方式不一样 GitHub是基于Pull Request 进行代码评审; GitLab是基于Merge Request 进行代码评审; Gerrit是基于Change Request 进行代码 ...
- margin属性总结,你想知道的这里都有
一.前言 在学习CSS时,遇到的很多问题都是和margin有关,这个小怪兽总是出其不意的让我的界面排版变的混乱,还让人摸不着头脑,原因还是在于我对他的一些属性没有进行一个深入的了解,导致我在设计之初就 ...
- svn创建新分支报错:svn: E155015: Aborting commit: XXX remains in conflict
用diea在对svn创建新分支的时候报错,错误为 svn: E155015: Aborting commit: XXX remains in conflict 百度和查阅资料后得知,此错误为分支被拉取 ...
- Linux平台安装MongoDB(转)
一.下载完安装包,并解压 tgz(以下演示的是 64 位 Linux上的安装) . curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x ...
- 使用 Cron4j 表达式 在 Solon 里开发定时任务
cron4j 是一个轻量级的Java任务调度工具.cron4j-solon-plugin 是 solon 对 cron4j 的适配插件 添加 maven 引用 <dependency> & ...
- Linux | 配置主机名称
配置主机名称 为了便于在局域 网中查找某台特定的主机,或者对主机进行区分,除了要有 IP 地址外,还要为主机配置一个主机名,主机之间可以通过这个类似于域名的名称来相互访问. 在 Linux 系统中,主 ...
- 深入学习Netty(4)——Netty编程入门
前言 从学习过BIO.NIO.AIO编程之后,就能很清楚Netty编程的优势,为什么选择Netty,而不是传统的NIO编程.本片博文是Netty的一个入门级别的教程,同时结合时序图与源码分析,以便对N ...
- python mysql 图片保存到表,从表中读出图片
fp = open(aa, 'rb') try: img = fp.read() except: print("图片打开出错") fp.close() return img #上面 ...