首页 > 其他分享 >wpf 自定义轮播图组件

wpf 自定义轮播图组件

时间:2023-08-18 13:22:39浏览次数:33  
标签:轮播 自定义 void private Part typeof new wpf public

 

 

轮播图组件代码:

[Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
[TemplatePart(Name = "Part_Grid",Type= typeof(Grid))]
[TemplatePart(Name = "Part_OldContentControl", Type = typeof(ContentControl))]
[TemplatePart(Name = "Part_NewContentControl", Type = typeof(ContentControl))]
[TemplatePart(Name = "Part_PreButton", Type = typeof(Button))]
[TemplatePart(Name = "Part_NextButton", Type = typeof(Button))]
[TemplatePart(Name = "Part_StackPanel", Type = typeof(StackPanel))]
public class Carousel:ItemsControl
{
#region Private Fields

private const string GridTemplateName = "Part_Grid";
private const string OldContentControlTemplateName = "Part_OldContentControl";
private const string NewContentControlTemplateName = "Part_NewContentControl";
private const string PreButtonTemplateName = "Part_PreButton";
private const string NextButtonTemplateName = "Part_NextButton";
private const string StackPanelTemplateName = "Part_StackPanel";

private DispatcherTimer _timer;
private Grid _grid;
private ContentControl _oldContentControl;
private ContentControl _newContentControl;
private Button _prevButton;
private Button _nextButton;
private StackPanel _stackPanel;
private int _pageIndex = -1;
private bool _templateLoaded;

#endregion
#region Public Properties

public TimeSpan Interval
{
get => (TimeSpan)GetValue(IntervalProperty);
set => SetValue(IntervalProperty, value);
}

public static readonly DependencyProperty IntervalProperty =
DependencyProperty.Register(nameof(Interval), typeof(TimeSpan), typeof(Carousel), new PropertyMetadata(TimeSpan.FromSeconds(3)));
public bool AutoPlay
{
get => (bool)GetValue(AutoPlayProperty);
set => SetValue(AutoPlayProperty, value);
}

public static readonly DependencyProperty AutoPlayProperty =
DependencyProperty.Register(nameof(AutoPlay), typeof(bool), typeof(Carousel), new PropertyMetadata(false,
(o, e) =>
{
if (o is Carousel d)
{
d.TimerSwitch((bool)e.NewValue);
}
}));

public Style PageButtonStyle
{
get => (Style)GetValue(PageButtonStyleProperty);
set => SetValue(PageButtonStyleProperty, value);
}

public static readonly DependencyProperty PageButtonStyleProperty =
DependencyProperty.Register(nameof(PageButtonStyle), typeof(Style), typeof(Carousel), new PropertyMetadata(default));

public int PageIndex
{
get => _pageIndex;
set
{
if(Items.Count==0)
return;

if(_pageIndex==value)
return;

if (value < 0)
_pageIndex = Items.Count - 1;
else if (value >= Items.Count)
_pageIndex = 0;
else
_pageIndex = value;

SwitchPageButton(_pageIndex);
}
}

#endregion

#region Events

public event EventHandler PreButtonClick;
public event EventHandler NextButtonClick;
public event EventHandler PageButtonClick;

#endregion

#region Constructor

static Carousel()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Carousel),new FrameworkPropertyMetadata(typeof(Carousel)));
}

public Carousel()
{
this.Loaded += (d, e) => SwitchPageButton(-1);
}

#endregion

#region Override Methods

public override void OnApplyTemplate()
{
_grid?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonBaseClick));
_prevButton?.RemoveHandler(ButtonBase.ClickEvent,new RoutedEventHandler(ButtonPreClick));
_nextButton?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonNextClick));

base.OnApplyTemplate();

_templateLoaded = false;
_grid = GetTemplateChild(GridTemplateName) as Grid;
_prevButton = GetTemplateChild(PreButtonTemplateName) as Button;
_nextButton=GetTemplateChild(NextButtonTemplateName) as Button;
_stackPanel=GetTemplateChild(StackPanelTemplateName) as StackPanel;
_oldContentControl = GetTemplateChild(OldContentControlTemplateName) as ContentControl;
_newContentControl=GetTemplateChild(NewContentControlTemplateName) as ContentControl;
_prevButton?.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonPreClick));
_nextButton?.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonNextClick));
_grid?.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonBaseClick));

_templateLoaded = true;
}

#endregion
#region Private Methods

private void TimerSwitch(bool isAutoPlay)
{
if (_timer != null)
{
_timer.Tick -= _timer_Tick;
_timer.Stop();
_timer = null;
}

if(!isAutoPlay)
return;

_timer = new DispatcherTimer(){ Interval = Interval};
_timer.Tick += _timer_Tick; ;
_timer.Start();
}

private void _timer_Tick(object sender, EventArgs e)
{
if(_templateLoaded)
PageIndex++;
}

private void SwitchPageButton(int index)
{
_stackPanel.Children.Clear();

if(Items.Count==0)
return;

for (int i = 0; i < Items.Count; i++)
{
_stackPanel.Children.Add(new RadioButton()
{
Style = PageButtonStyle
});
}

if (index<0)
index = Items.Count-1;

if (index > Items.Count - 1)
index = 0;

if (_stackPanel.Children[index] is RadioButton btn)
{
btn.IsChecked = true;
btn.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent, btn));
SwitchPage();
}
}

private void SwitchPage()
{
if(Items.Count==0)
return;

if (Items[PageIndex] is FrameworkElement currentElement)
{
var oldContent = _newContentControl.Content;
_newContentControl.Content = null;

currentElement.Loaded += async (s, e) =>
{
var element = s as FrameworkElement;
await element.SlideAndFadeInAsync(AnimationSlideInDirection.Right, true,1.0f);
};

currentElement.Unloaded += async (s, e) =>
{
var element = s as FrameworkElement;
await element.SlideAndFadeOutAsync(AnimationSlideInDirection.Left,1.0f);
};
_oldContentControl.Content = oldContent;

Task.Delay((int)(1 * 1000)).ContinueWith((t) =>
{
Application.Current.Dispatcher.Invoke(() => _oldContentControl.Content = null);
});
_newContentControl.Content = currentElement;
}
}

private void ButtonBaseClick(object sender, RoutedEventArgs e)
{
var _selectedButton = e.OriginalSource as RadioButton;

var index = _stackPanel.Children.IndexOf(_selectedButton);
if (index != -1)
{
PageIndex = index;
}

PageButtonClick?.Invoke(sender, e);
}
private void ButtonPreClick(object sender, RoutedEventArgs e)
{
PageIndex--;
PreButtonClick?.Invoke(sender,e);
}

private void ButtonNextClick(object sender, RoutedEventArgs e)
{
PageIndex++;
NextButtonClick?.Invoke(sender,e);
}

#endregion
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
style

<Style TargetType="{x:Type controls1:Carousel}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls1:Carousel}">
<Grid
x:Name="Part_Grid"
Background="{TemplateBinding Background}"
ClipToBounds="True">
<ContentControl x:Name="Part_OldContentControl" />
<ContentControl x:Name="Part_NewContentControl" />

<Button
x:Name="Part_PreButton"
Width="60"
Height="100"
Margin="15,0,0,0"
Padding="15"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Background="DarkGray"
BorderThickness="0"
Opacity="0.7"
Visibility="Hidden">
<Button.Content>
<Path
Data="M 15,50 30,18 33,20 19,50 33,80 30,82 z"
Fill="White"
Stretch="Uniform" />
</Button.Content>
</Button>
<Button
x:Name="Part_NextButton"
Width="60"
Height="100"
Margin="0,0,15,0"
Padding="15"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Background="DarkGray"
BorderThickness="0"
Opacity="0.7"
Visibility="Hidden">
<Button.Content>
<Path
Data="M 45,50 30,18 27,20 41,50 27,80 30,82 z"
Fill="White"
Stretch="Uniform" />
</Button.Content>
</Button>

<StackPanel
x:Name="Part_StackPanel"
Margin="0,0,0,10"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Orientation="Horizontal" />
</Grid>

<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Part_PreButton" Property="Visibility" Value="Visible" />
<Setter TargetName="Part_NextButton" Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
使用

Border Grid.Row="0">
<controls:Carousel
x:Name="myCarousel"
AutoPlay="True"
NextButtonClick="MyCarousel_OnNextButtonClick"
PreButtonClick="MyCarousel_OnPreButtonClick">
<controls:Carousel.Items>
<Image Source="/AutoPOS;component/Asset/Images/1.jpg" Stretch="Fill" />
<Image Source="/AutoPOS;component/Asset/Images/2.jpeg" Stretch="Fill" />
<Image Source="/AutoPOS;component/Asset/Images/3.png" Stretch="Fill" />
<MediaElement
LoadedBehavior="Play"
MediaEnded="MediaElement_OnMediaEnded"
MediaOpened="MediaElement_OnMediaOpened"
Source="./Asset/Vedio/单依纯-永不失联的爱.mkv"
Stretch="Fill" />
</controls:Carousel.Items>
</controls:Carousel>
</Border>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
后台代码:

public partial class HomeView : UserControl
{
public HomeView()
{
InitializeComponent();
}

private void MediaElement_OnMediaOpened(object sender, RoutedEventArgs e)
{
myCarousel.AutoPlay=false;
}

private void MediaElement_OnMediaEnded(object sender, RoutedEventArgs e)
{
myCarousel.AutoPlay=true;
}

private void MyCarousel_OnPreButtonClick(object sender, EventArgs e)
{
myCarousel.AutoPlay = true;
}

private void MyCarousel_OnNextButtonClick(object sender, EventArgs e)
{
myCarousel.AutoPlay = true;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
效果图:

 

注意的事项:
视频资源请指定内容,较新复制选项
可自实现sizechanged,visiblechanged实现变化逻辑
timer请先解除事件绑定和停止计时器,再置为null
carousel组件留出了许多接口,比如在播放视频时希望视频播放完成再去自动播放轮播图。可以注册事件处理。还留出相应的事件如下

public event EventHandler PreButtonClick;
public event EventHandler NextButtonClick;
public event EventHandler PageButtonClick;
1
2
3
也可以使用mvvm绑定到items,autoplay等属性
————————————————
版权声明:本文为CSDN博主「pw8992134」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/pw8992134/article/details/129622176

标签:轮播,自定义,void,private,Part,typeof,new,wpf,public
From: https://www.cnblogs.com/webenh/p/17640230.html

相关文章

  • WPF ListBox 控件绑定 Binding
     当我们需要用到循环的列表内容,并且模板化程度高的时候,建议使用 ListBox 来做绑定。XAML:<Window.DataContext><local:VMTempTest/></Window.DataContext><StackPanelMargin="10,0,0,50"Orientation="Vertical"><TextBlockText="ListBo......
  • WebView2在WPF中的应用
    开发环境运行环境:.Net6开发环境:VisualStudio202217.1.3框架语言:WPF安装WebView2通过PackageManager控制台安装Install-PackageMicrosoft.Web.WebView2通过Nuget包管理器安装在窗体中添加名字空间:xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;asse......
  • wangEditor 自定义上传图片
    //需要项目后台提供上传接口uploadFile下载接口FILE_URL:Object.defineProperties(Vue.prototype,{FILE_URL:{value:function(fileId){if(!fileId){return}return(process.env.VUE_APP_REMOTE_URL+'mi'+......
  • 为WPF框架Prism注册Nlog日志服务
    这篇文章介绍了为WPF框架Prism注册Nlog日志服务的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 无论是Nlog还是Serilog,它们都提供了如何快速在各类应用程序当中的快速使用方法。尽管,你现在无论是在WPF或者ASP.NETCore当中,......
  • WPF的5种绑定模式(Mode)
    一:WPF的5种绑定模式(Mode)WPF的绑定模式(mode)是枚举的枚举值共有5个1:OneWay(源变就更新目标属性)2:TwoWay(源变就更新目标并且目标变就更新源)3:OneTime(只根据源来设置目标,以后都不会变)4:OneWayToSource(与OneWay相反)5:Default(可以单向或双向,是靠被值定的源或目标是否有get或set来指定的)所......
  • WPF 设置第二次打开程序直接弹出第一次打开的程序
    激活已经打开窗口函数[DllImport("user32.dll")]privatestaticexternboolSetForegroundWindow(IntPtrhWnd);[DllImport("user32.dll")]privatestaticexternboolShowWindowAsync(IntPtrhWnd,intnCmdShow);[DllImport("user32.dll")]privatest......
  • vue无缝循环轮播
    在网上看了几个无缝循环轮播的实现方法,使用方法都比较复杂,所以这里提供一种比较简单的实现方式gitee:https://gitee.com/philippines-kisses-snow/rotation结构和理论梳理理论轮播的原理就是通过translateY/translateX移动轮播容器+过渡达到轮播项上下左右轮播效果的,为了达......
  • c# - 如何在圆角 WPF 窗体中创建圆角矩形?
    我正在WPF中创建一个应用程序,我想要圆角。收到。现在窗体是无边框的,我正在尝试创建一个圆角矩形并将其放在顶部,使其看起来像Windows应用程序的顶部栏。我做不到。这是我的代码:<BorderCornerRadius="50,0,50,0"BorderBrush="Black"BorderThickness="2"Background="......
  • 黑魂235 自定义playable
    首先去Unity官网下载这个CustomPlayable的免费素材。然后导入工程项目里。在Director物体里可以导入新的Track轨。 ......
  • WPF利用依赖属性和命令编写自定义控件
    以实例讲解(大部分讲解在代码中)1,新建一个WPF项目,添加一个用户控件之后在用户控件里面添加几个控件用作测试,12345678910111213141516171819<UserControlx:Class="SelfControlDenpendy.SelfControl"             xmlns="http://schem......