跳到主要内容

github/tai

公开

Tai · Windows 软件与网站使用时长统计。上游 Planshit/Tai 的源码镜像,非灵栈原创;MIT 许可。来源:https://github.com/Planshit/Tai 。本次为手动同步,暂不提供安装包。

浏览文件

DatePickerBar.cs

465 行 · 14.5 KB历史下载
1using System;
2using System.Collections.Generic;
3using System.Collections.ObjectModel;
4using System.Collections.Specialized;
5using System.Diagnostics;
6using System.Linq;
7using System.Text;
8using System.Windows;
9using System.Windows.Controls;
10using System.Windows.Controls.Primitives;
11using System.Windows.Input;
12using System.Windows.Media;
13using System.Windows.Media.Animation;
14using UI.Controls.List;
15using UI.Controls.Navigation.Models;
16
17namespace UI.Controls.DatePickerBar
18{
19 public class DatePickerBar : Control
20 {
21 public DatePickerShowType ShowType
22 {
23 get { return (DatePickerShowType)GetValue(ShowTypeProperty); }
24 set { SetValue(ShowTypeProperty, value); }
25 }
26 public static readonly DependencyProperty ShowTypeProperty =
27 DependencyProperty.Register("ShowType", typeof(DatePickerShowType), typeof(DatePickerBar), new PropertyMetadata(DatePickerShowType.Day, new PropertyChangedCallback(OnShowTypeChanged)));
28
29 private static void OnShowTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
30 {
31 var control = d as DatePickerBar;
32 if (e.NewValue != e.OldValue)
33 {
34 control.Render(control.SelectedDate);
35 }
36 }
37
38 public DateTime SelectedDate
39 {
40 get { return (DateTime)GetValue(SelectedDateProperty); }
41 set { SetValue(SelectedDateProperty, value); }
42 }
43 public static readonly DependencyProperty SelectedDateProperty =
44 DependencyProperty.Register("SelectedDate", typeof(DateTime), typeof(DatePickerBar), new PropertyMetadata(new PropertyChangedCallback(OnSelectedItemChanged)));
45
46 private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
47 {
48 var control = d as DatePickerBar;
49 if (e.NewValue != e.OldValue)
50 {
51 //DateTime newDateTime = DateTime.Now;
52
53 DateTime.TryParse(e.NewValue.ToString(), out DateTime newDateTime);
54
55 control.ScrollToActive(newDateTime);
56 control.UpdateDateString();
57 }
58 }
59
60
61 public string SelectedDateString
62 {
63 get { return (string)GetValue(SelectedDateStringProperty); }
64 set { SetValue(SelectedDateStringProperty, value); }
65 }
66 public static readonly DependencyProperty SelectedDateStringProperty =
67 DependencyProperty.Register("SelectedDateString", typeof(string), typeof(DatePickerBar));
68
69 /// <summary>
70 /// 是否显示日期选择弹出层
71 /// </summary>
72 public bool IsShowDatePickerPopup
73 {
74 get { return (bool)GetValue(IsShowDatePickerPopupProperty); }
75 set { SetValue(IsShowDatePickerPopupProperty, value); }
76 }
77 public static readonly DependencyProperty IsShowDatePickerPopupProperty =
78 DependencyProperty.Register("IsShowDatePickerPopup", typeof(bool), typeof(DatePickerBar));
79
80
81
82
83
84 private StackPanel Container;
85 private ScrollViewer ScrollViewer;
86 private Dictionary<DateTime, DatePickerBarItem> ItemsDictionary;
87 private List<DateTime> DateList;
88
89 private int dataCount = 0;
90 private int renderIndex = 0;
91 // 选中标记块
92 private Border ActiveBlock;
93 // 动画
94 Storyboard storyboard;
95 // 日期选择弹出层
96 private Popup DatePickerPopup;
97 private BaseList YearsList, MonthsList;
98 private Border Date;
99 private ScrollViewer YearsListScrollViewer;
100 private StackPanel MonthSelect;
101 public DatePickerBar()
102 {
103 DefaultStyleKey = typeof(DatePickerBar);
104 ItemsDictionary = new Dictionary<DateTime, DatePickerBarItem>();
105 DateList = new List<DateTime>();
106 storyboard = new Storyboard();
107 }
108
109
110
111 public override void OnApplyTemplate()
112 {
113 base.OnApplyTemplate();
114 Container = GetTemplateChild("Container") as StackPanel;
115 ActiveBlock = GetTemplateChild("ActiveBlock") as Border;
116 ScrollViewer = GetTemplateChild("ScrollViewer") as ScrollViewer;
117 DatePickerPopup = GetTemplateChild("DatePickerPopup") as Popup;
118 Date = GetTemplateChild("Date") as Border;
119 YearsList = GetTemplateChild("YearsList") as BaseList;
120 MonthsList = GetTemplateChild("MonthsList") as BaseList;
121 YearsListScrollViewer = GetTemplateChild("YearsListScrollViewer") as ScrollViewer;
122 MonthSelect = GetTemplateChild("MonthSelect") as StackPanel;
123
124 Init();
125
126 // 渲染日期
127 Render(DateTime.Now);
128
129
130 }
131
132 /// <summary>
133 /// 初始化控件数据
134 /// </summary>
135 private void Init()
136 {
137 DatePickerPopup.Closed += (e, c) =>
138 {
139 IsShowDatePickerPopup = false;
140 VisualStateManager.GoToState(this, "Normal", true);
141 };
142
143 Date.MouseEnter += (e, c) =>
144 {
145 VisualStateManager.GoToState(this, "DateMouseOver", true);
146 };
147 Date.MouseLeave += (e, c) =>
148 {
149 VisualStateManager.GoToState(this, "Normal", true);
150 };
151 Date.MouseLeftButtonUp += (e, c) =>
152 {
153 IsShowDatePickerPopup = true;
154 VisualStateManager.GoToState(this, "ShowPopup", true);
155 };
156
157 // 填充年份数据
158 YearsList.SelectedItem = DateTime.Now.Year.ToString();
159 //YearsList.SelectedItem = "2073";
160
161 for (int i = 2021; i <= DateTime.Now.Year; i++)
162 {
163 YearsList.Items.Add(i.ToString());
164 }
165 YearsList.SelectedItemChanged += DateChanged;
166
167 if (ShowType == DatePickerShowType.Day)
168 {
169 // 填充月份数据
170 MonthSelect.Visibility = Visibility.Visible;
171
172 MonthsList.SelectedItem = DateTime.Now.Month.ToString();
173 //MonthsList.SelectedItem = "1";
174
175 for (int i = 1; i <= 12; i++)
176 {
177 MonthsList.Items.Add(i.ToString());
178 }
179
180 MonthsList.SelectedItemChanged += DateChanged;
181
182 }
183 }
184
185 private void DateChanged(object sender, EventArgs e)
186 {
187 if (ShowType == DatePickerShowType.Day)
188 {
189 SelectedDate = new DateTime(int.Parse(YearsList.SelectedItem), int.Parse(MonthsList.SelectedItem), 1);
190 }
191 else
192 {
193 SelectedDate = new DateTime(int.Parse(YearsList.SelectedItem), 1, 1);
194 }
195 Render(SelectedDate);
196 }
197
198 private void UpdateDateString()
199 {
200 if (ShowType == DatePickerShowType.Day)
201 {
202 SelectedDateString = SelectedDate.ToString("yyyy/MM");
203 }
204 else
205 {
206 SelectedDateString = SelectedDate.ToString("yyyy");
207 }
208 }
209 private void AddItem(DateTime date)
210 {
211 if (Container != null)
212 {
213 if (DateList.IndexOf(date) != -1)
214 {
215 return;
216 }
217 renderIndex++;
218 var control = new DatePickerBarItem();
219 control.Title = date.Day.ToString();
220 control.Date = date;
221 control.MouseUp += (e, c) =>
222 {
223 if (date > DateTime.Now.Date)
224 {
225 return;
226 }
227 ScrollToActive(date);
228 };
229
230 if (renderIndex == dataCount)
231 {
232
233 control.Loaded += (e, c) =>
234 {
235
236 if (SelectedDate == DateTime.MinValue)
237 {
238 if (date == DateTime.Now.Date)
239 {
240 SelectedDate = DateTime.Now.Date;
241 }
242 }
243 else
244 {
245 ScrollToActive(SelectedDate);
246 }
247 };
248 }
249 // 后一天
250 int next = DateList.IndexOf(date.AddDays(+1));
251
252 if (next != -1)
253 {
254 int index = next - 1;
255 if (index < 0)
256 {
257 index = 0;
258 }
259 DateList.Insert(index, date);
260 ItemsDictionary.Add(date, control);
261 Container.Children.Insert(index, control);
262 }
263 else
264 {
265 DateList.Add(date);
266 ItemsDictionary.Add(date, control);
267 Container.Children.Add(control);
268 }
269 //if (Data.IndexOf(item) == Data.Count - 1)
270 //{
271 // control.Loaded += (e, c) =>
272 // {
273 // ScrollToActive();
274 // };
275 //}
276 //Container.Children.Add(control);
277 //ItemsDictionary.Add(control);
278 }
279 }
280
281
282
283 private void Render(DateTime date)
284 {
285 if (Container == null)
286 {
287 return;
288 }
289 dataCount = 0;
290 renderIndex = 0;
291
292 DateList.Clear();
293 ItemsDictionary.Clear();
294 Container.Children.Clear();
295
296 if (ShowType == DatePickerShowType.Day)
297 {
298 dataCount = DateTime.DaysInMonth(date.Year, date.Month);
299
300 //// 前30天
301 //for (int i = 1; i < 31; i++)
302 //{
303 // AddItem(date.Date.AddDays(-i));
304 //}
305
306 //AddItem(date.Date);
307 for (int i = 1; i <= dataCount; i++)
308 {
309 AddItem(new DateTime(date.Year, date.Month, i));
310 }
311 //// 后十天
312 //for (int i = 1; i < 11; i++)
313 //{
314 // AddItem(DateTime.Now.Date.AddDays(+i));
315 //}
316 }
317
318 if (ShowType == DatePickerShowType.Month)
319 {
320 dataCount = 12;
321
322 for (int i = 1; i < 13; i++)
323 {
324 var data = new DateTime(date.Year, i, 1);
325 AddMonthItem(data);
326 }
327 }
328
329
330
331 }
332
333 private void AddMonthItem(DateTime date)
334 {
335
336 if (Container != null)
337 {
338 if (DateList.IndexOf(date) != -1)
339 {
340 return;
341 }
342 renderIndex++;
343
344 var control = new DatePickerBarItem();
345 control.Title = date.Month.ToString();
346 control.Date = date;
347 control.MouseUp += (e, c) =>
348 {
349 if (date > DateTime.Now.Date)
350 {
351 return;
352 }
353 ScrollToActive(date);
354 };
355
356 if (renderIndex == dataCount)
357 {
358 control.Loaded += (e, c) =>
359 {
360 if (SelectedDate == DateTime.MinValue)
361 {
362 if (date.Year == DateTime.Now.Date.Year
363 && date.Month == DateTime.Now.Date.Month)
364 {
365 SelectedDate = date;
366 }
367 }
368 else
369 {
370 ScrollToActive(SelectedDate);
371 }
372 };
373 }
374
375
376 DateList.Add(date);
377 ItemsDictionary.Add(date, control);
378 Container.Children.Add(control);
379 }
380 }
381
382 private void ScrollToActive(DateTime date)
383 {
384
385 if (ItemsDictionary.Count == 0)
386 {
387 return;
388 }
389 if (ShowType == DatePickerShowType.Month)
390 {
391 date = new DateTime(date.Year, date.Month, 1);
392 }
393 else
394 {
395 date = new DateTime(date.Year, date.Month, date.Day);
396 }
397
398 if (!ItemsDictionary.ContainsKey(date))
399 {
400 return;
401 }
402 if (ItemsDictionary.ContainsKey(SelectedDate))
403 {
404 // 如果存在旧的选中,先取消
405 ItemsDictionary[SelectedDate].IsSelected = false;
406 }
407
408 if (date != SelectedDate)
409 {
410 SelectedDate = date;
411 }
412
413
414 ItemsDictionary[date].IsSelected = true;
415
416 var control = ItemsDictionary[SelectedDate];
417
418 Point relativePoint = control.TransformToAncestor(Container).Transform(new Point(0, 0));
419
420 double scrollTo = relativePoint.X - (ScrollViewer.ActualWidth / 2) + control.ActualWidth / 2;
421 if (scrollTo < 0)
422 {
423 scrollTo = 0;
424 }
425
426 ScrollViewer.ScrollToHorizontalOffset(scrollTo);
427
428
429 //if (oldSelectedIndex > ItemsDictionary.Count || ItemsDictionary.Count == 0)
430 //{
431 // return;
432 //}
433 // 获取选中项
434
435 //var item = ItemsDictionary[SelectedIndex];
436 //var oldSelectedItem = ItemsDictionary[oldSelectedIndex];
437
438
439 // 选中项的坐标
440 //Point relativePoint = item.TransformToAncestor(this).Transform(new Point(0, 0));
441
442 // 创建动画
443
444
445
446 //storyboard.Children.Clear();
447 //DoubleAnimation scrollAnimation = new DoubleAnimation();
448 //double scrollX = relativePoint.X - 10;
449 //scrollX = scrollX < 0 ? 0 : scrollX;
450 //scrollAnimation.To = scrollX;
451
452 //scrollAnimation.EasingFunction = new SineEase() { EasingMode = EasingMode.EaseIn };
453 //Storyboard.SetTarget(scrollAnimation, ActiveBlock);
454 //Storyboard.SetTargetProperty(scrollAnimation, new PropertyPath("RenderTransform.Children[0].X"));
455
456 //scrollAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.15));
457
458
459 //storyboard.Children.Add(scrollAnimation);
460
461
462 //storyboard.Begin();
463 }
464 }
465}