实现效果

带定时器的轮播图

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 控件轮播的更多相关文章

  1. WPF自定义控件二:Border控件与TextBlock控件轮播动画

    需求:实现Border轮播动画与TextBlock动画 XAML代码如下: <Window.Resources> <Storyboard x:Key="OnLoaded1& ...

  2. WPF自定义控件之图片控件 AsyncImage

    AsyncImage 是一个封装完善,使用简便,功能齐全的WPF图片控件,比直接使用Image相对来说更加方便,但它的内部仍然使用Image承载图像,只不过在其基础上进行了一次完善成熟的封装 Asyn ...

  3. WPF后台设置xaml控件的样式System.Windows.Style

    WPF后台设置xaml控件的样式System.Windows.Style 摘-自 :感谢 作者: IT小兵   http://3w.suchso.com/projecteac-tual/wpf-zhi ...

  4. 在WPF中使用WinForm控件方法

    1.      首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,System.Windows.Forms.dll. 2.      在要使用WinForm控 ...

  5. WPF Step By Step 控件介绍

    WPF Step By Step 控件介绍 回顾 上一篇,我们主要讨论了WPF的几个重点的基本知识的介绍,本篇,我们将会简单的介绍几个基本控件的简单用法,本文会举几个项目中的具体的例子,结合这些 例子 ...

  6. 背水一战 Windows 10 (79) - 自定义控件: Layout 系统, 控件模板, 事件处理

    [源码下载] 背水一战 Windows 10 (79) - 自定义控件: Layout 系统, 控件模板, 事件处理 作者:webabcd 介绍背水一战 Windows 10 之 控件(自定义控件) ...

  7. Wpf使用Winform控件后Wpf元素被Winform控件遮盖问题的解决

    有人会说不建议Wpf中使用Winform控件,有人会说建议使用Winform控件在Wpf下的替代方案,然而在实际工作中由于项目的特殊需求,考虑到时间.成本等因素,往往难免会碰到在WPF中使用Winfr ...

  8. WPF自定义选择年月控件详解

    本文实例为大家分享了WPF自定义选择年月控件的具体代码,供大家参考,具体内容如下 封装了一个选择年月的控件,XAML代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  9. WPF学习- AllowDrop 用户控件启用拖放功能

    知识点: 创建自定义用户控件(UserControl) 使用户控件成为拖动源 使用户控件成为放置目标 使面板能够接收从用户控件放置的数据 创建项目: 1.新建WPF项目(Wpf-AllowDrop) ...

随机推荐

  1. Git常用命令超级详细(全网最详细)

    1.新建代码库 1.1在当前目录新建一个 Git 代码库 $ git init 1.2新建一个目录,将其初始化为 Git 代码库 $ git init [project-name] 1.3下载一个项目 ...

  2. 【转】JAVA四种引用(强引用,弱引用,软引用,虚引用)

    转自:http://www.cnblogs.com/gudi/p/6403953.html 1.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器 ...

  3. Docker:PostgreSQL-11配置数据持久化

    卷的原理图: 主机中的本地目录作为Docker容器内的持久存储卷装载,以便在主机和Docker容器之间共享数据.如果主机希望访问或定期备份在Docker容器内运行的DB服务器写入文件夹的数据或数据库, ...

  4. .h .cpp区别

    首先,我们可以将所有东西都放在一个.cpp文件内. 然后编译器就将这个.cpp编译成.obj,obj是什么东西? 就是编译单元了.一个程序,可以由一个编译单元组成, 也可以有多个编译单元组成. 如果你 ...

  5. Redis解读(4):Redis中HyperLongLog、布隆过滤器、限流、Geo、及Scan等进阶应用

    Redis中的HyperLogLog 一般我们评估一个网站的访问量,有几个主要的参数: pv,Page View,网页的浏览量 uv,User View,访问的用户 一般来说,pv 或者 uv 的统计 ...

  6. RedHat7.4安装在个人电脑(笔记本)中安装遇到的问题总结

    RedHat7.4安装在个人电脑(笔记本)中安装 以下纯属个人在安装过程中遇到问题的一些总结,如果有描述不恰当的地方,还请给予指出,欢迎大家评论和交流. 物理主机的配置: 硬件配置: 华硕A456U笔 ...

  7. like %和-的区别与使用

    通配符的分类: %百分号通配符:表示任何字符出现任意次数(可以是0次). 下划线通配符:表示只能匹配单个字符,不能多也不能少,就是一个字符. like操作符: LIKE作用是指示mysql后面的搜索模 ...

  8. 如何写好技术文档——来自Google十多年的文档经验

    本文大部分内容翻译总结自<Software Engineering at Google> 第10章节 Documentation. 另外,该书电子版近日已经可以免费下载了 https:// ...

  9. 深入刨析tomcat 之---第9篇 how tomcat works 第9章,Session的实现 关于request.setContext(context)

    writedby 张艳涛,在学第9章session的时候,做了个实验在给的demo代码中添加了 package com.zyt.tomcat.ex09.core; public class Simpl ...

  10. jvm源码解读--18 Java的start()方法解读 以及 wait 和notify流程图

    drawwed by 张艳涛 and get info from openjdk8 还有一个图