原文:【C#】wpf自定义calendar日期选择控件的样式

  • 首先上图看下样式
  • 原理
    • 总览
    • ItemsControl内容的生成
  • 实现
    • 界面的实现
    • 后台ViewModel的实现

首先上图,看下样式


原理

1. 总览:

Calendar本质上是一个6x7的列表,这个列表可以用ItemsControl来实现。其填充的每一个item都是一个自定义样式的Button,Button外面是一个圆形的border。根据Button按钮的IsEnabled状态,设置foreground以达到灰色不点击的效果。

2. ItemsControl内容的生成:

主要是想办法生成第一行第一列的日期,其他的日期只需要DateTime.AddDays(i)即可。代码参考:

private void SetCalendar(int year, int month)
{_days.Clear();//请忽略DateTime datetime = new DateTime(year, month, 1);int week = (int)datetime.DayOfWeek;//获取指定月份的1号是周几datetime = datetime.AddDays(1 - week);for (int i = 0; i < 42; i++){_days.Add(datetime.AddDays(i));}OnPropertyChanged("Days");//请忽略
}

首先,将当前年月传入,获取到当前月份的第一天是周几,然后推算出ItemsControl的第一行第一列的Datetime,最后就是顺次相加即可。

实现

1. 界面的实现

先上代码:

<Grid  Grid.RowSpan="4" Margin="0,54,0,0" Visibility="{Binding IsShowCalendar,Converter={StaticResource BoolToVisibilityCollapseConverter}}" Background="White" Width="350" HorizontalAlignment="Right"><Grid.RowDefinitions><RowDefinition Height="50"></RowDefinition><RowDefinition Height="auto"></RowDefinition><RowDefinition Height="auto"></RowDefinition><RowDefinition Height="*"></RowDefinition></Grid.RowDefinitions><StackPanel HorizontalAlignment="Center" Orientation="Horizontal"><Button VerticalAlignment="Center"  Command="{Binding YearCommand}" CommandParameter="Pre" Style="{StaticResource TransparentButtonStyle}"><Button.Content><TextBlock Text="&lt;" FontSize="20"></TextBlock></Button.Content></Button><TextBlock VerticalAlignment="Center" FontSize="15" Text="{Binding CurrentYear}"></TextBlock><Button VerticalAlignment="Center"  Command="{Binding YearCommand}" CommandParameter="Next" Style="{StaticResource TransparentButtonStyle}"><Button.Content><TextBlock Text="&gt;" FontSize="20"></TextBlock></Button.Content></Button><Button Margin="50,10,10,10" VerticalAlignment="Center" Command="{Binding MonthCommand}" CommandParameter="Pre" Style="{StaticResource TransparentButtonStyle}"><Button.Content><TextBlock Text="&lt;" FontSize="20"></TextBlock></Button.Content></Button><TextBlock VerticalAlignment="Center" Text="{Binding CurrentMonth}" FontSize="15"></TextBlock><Button VerticalAlignment="Center" Command="{Binding MonthCommand}" CommandParameter="Next" Style="{StaticResource TransparentButtonStyle}"><Button.Content><TextBlock Text="&gt;" FontSize="20"></TextBlock></Button.Content></Button></StackPanel><UniformGrid Grid.Row="1" Columns="7"><TextBlock Text="MON" TextAlignment="Center"></TextBlock><TextBlock Text="TUE" TextAlignment="Center"></TextBlock><TextBlock Text="WED" TextAlignment="Center"></TextBlock><TextBlock Text="THU" TextAlignment="Center"></TextBlock><TextBlock Text="FRI" TextAlignment="Center"></TextBlock><TextBlock Text="SAT" TextAlignment="Center"></TextBlock><TextBlock Text="SUN" TextAlignment="Center"></TextBlock></UniformGrid><ItemsControl Grid.Row="2" ScrollViewer.HorizontalScrollBarVisibility="Auto"ScrollViewer.VerticalScrollBarVisibility="Auto"ItemsSource="{Binding Days}"><ItemsControl.ItemTemplate><DataTemplate><Button Background="{Binding Converter={StaticResource BACKUP_DateTimeToColorConverter}}"  Style="{StaticResource CalendarTransparentButtonStyle}"Content="{Binding Converter={StaticResource BACKUP_DateTimeToDayConverter}}" Command="{Binding DataContext.ChooseDateCommand,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}}" CommandParameter="{Binding}"MouseDoubleClick="Button_MouseDoubleClick"><Button.Foreground><MultiBinding Converter="{StaticResource BACKUP_DateTimeToForegroundMultiConverter}"><Binding></Binding><Binding Path="DataContext.CurrentMonth" RelativeSource="{RelativeSource FindAncestor,AncestorType={x:Type Window}}"></Binding></MultiBinding></Button.Foreground><Button.IsEnabled><MultiBinding Converter="{StaticResource BACKUP_DateTimeToEnableMultiConverter}"><Binding></Binding><Binding Path="DataContext.CutoffDayBegin" RelativeSource="{RelativeSource FindAncestor,AncestorType={x:Type Window}}"></Binding><Binding Path="DataContext.CutoffDayEnd" RelativeSource="{RelativeSource FindAncestor,AncestorType={x:Type Window}}"></Binding></MultiBinding></Button.IsEnabled></Button></DataTemplate></ItemsControl.ItemTemplate><ItemsControl.ItemsPanel><ItemsPanelTemplate><UniformGrid Columns="7"></UniformGrid></ItemsPanelTemplate></ItemsControl.ItemsPanel></ItemsControl><StackPanel Grid.Row="3" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,31" Orientation="Horizontal"><Button Content="Cancel" Style="{StaticResource btnSecondaryStyle}" Grid.Row="2" Command="{Binding HideCalendarCommand}"></Button><Button Content="{Binding CalendarSetText}" Style="{StaticResource btnPrimaryStyle}" Grid.Row="2" Command="{Binding HideCalendarCommand}"></Button></StackPanel></Grid>

其中,大量用到了Binding和MVVM,如果对方面还不是很扎实,可以参考下刘铁锰的视频.
这段代码中,主要部分是ItemsControl的ItemsSource绑定。这里绑定的是Days,其类型是

public ObservableCollection<DateTime> _days = new ObservableCollection<DateTime>();public ObservableCollection<DateTime> Days{get{return _days;}}

在设置Button的前景色和IsEnabled状态的时候,你也看到了用的是MultiBinding,并定义了两个Converter:
1. DateTimeToForegroundMultiConverter

 class DateTimeToForegroundMultiConverter : IMultiValueConverter{public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture){DateTime dt=new DateTime();if(values[0] is DateTime){dt = (DateTime)values[0];}int currentMonth;Int32.TryParse(values[1].ToString(), out currentMonth);if (dt.Month == currentMonth){if(dt.ToShortDateString()==DateTime.Now.ToShortDateString()){return new SolidColorBrush(Colors.White);}else{return new SolidColorBrush(Colors.Black);}}else{return new SolidColorBrush(Colors.Gray);}}public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture){return null;}}

2. DateTimeToEnableMultiConverter

 class DateTimeToEnableMultiConverter : IMultiValueConverter{public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture){DateTime currentDay, cutoffDayBegin,cutoffDayEnd;if(values[0] is DateTime&&values[1] is DateTime&&values[2] is DateTime){currentDay = (DateTime)values[0];cutoffDayBegin = (DateTime)values[1];cutoffDayEnd = (DateTime)values[2];if (DateTime.Compare(currentDay, cutoffDayBegin) >= 0 && DateTime.Compare(currentDay, cutoffDayEnd) <= 0){return true;}else{return false;}}else{return false;}}public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture){return null;}}

2. 后台ViewModel的实现

其实后台没有什么代码,有一个SetCalendar方法,在月份或者年份发生变动的时候调用一下即可。

private void SetCalendar(int year, int month){_days.Clear();DateTime datetime = new DateTime(year, month, 1);int week = (int)datetime.DayOfWeek;datetime = datetime.AddDays(1 - week);for (int i = 0; i < 42; i++){_days.Add(datetime.AddDays(i));}OnPropertyChanged("Days");}

还有一个就是Button点击之后的Command命令

 private void exeChooseDate(object obj){DateTime dt;DateTime.TryParse(obj.ToString(), out dt);CurrentMonth = dt.Month;CurrentYear = dt.Year;}

Button每点击一次,就会执行一次这个方法,CurrentMonth和CurrentYear这两个属性的值就会被更改,一些来决定是否需要重新绘制UI切换的上一个/下一个月份。

CurrentMonth和CurrentYear属性见下:

private int _currentYear = 2010;public int CurrentYear{get{return _currentYear;}set{if (_currentYear != value && value > 1978 && value < 9999){_currentYear = value;OnPropertyChanged("CurrentYear");SetCalendar(_currentYear, CurrentMonth);}}}private int _currentMonth = 1;public int CurrentMonth{get{return _currentMonth;}set{if (_currentMonth != value && value < 13 && value > 0){_currentMonth = value;OnPropertyChanged("CurrentMonth");SetCalendar(CurrentYear, _currentMonth);}}}

【C#】wpf自定义calendar日期选择控件的样式相关推荐

  1. java界面日期选择控件,JavaFX界面设计之时间选择器(1)

    本章我们主要介绍javafX时间选择器的使用,描述了DatePicker控件的基本特性. javaFX的DatePicker控件可以让我们从一个给定的日历中选择一天,主要用于网站或应用中需要用户输入一 ...

  2. ExtJS6.0扩展日期选择控件为也可以选择时间

    PS:ExtJS自带的日期选择控件只能够选择日期,但是现在的需求需要精确到秒,所以在网上搜索了一些例子(大部分是4.0的)作为参考,然后改出了6.0可用的一个日期时间选择控件. 1.找到extjs6. ...

  3. java 的日期选择控件_Java日期选择控件

    一起学习 一次项目研发中需要日期时间选择控件, 网上提供的不多, 且质量一般, 所以只好自己做,参考了 网上某位同学的 作品 Jave 日期选择控件 DateChooser . 目前的代码将日期时间选 ...

  4. js 跨域的问题 (同一个主域名不同的二级域名下的跨域问题) 解决 WdatePicker.js my97日期选择控件

    js 跨域的问题 (同一个主域名不同的二级域名下的跨域问题) 解决 WdatePicker.js my97日期选择控件 参考文章: (1)js 跨域的问题 (同一个主域名不同的二级域名下的跨域问题) ...

  5. [Ext JS 4] 实战之 带week(星期)的日期选择控件(三)

    前言 在 [Ext JS 4] 实战之 带week(星期)的日期选择控件(二) 的最后,有提到一个解决方案. 不过这方案有一个条件  ==> "2. 每年的周数从(1-52), 如果超 ...

  6. [Ext JS 4] 实战之 带week(星期)的日期选择控件(二)

    前言 JavaScript 中的日期和时间 [Ext JS 4] 实战之 带week(星期)的日期选择控件(一) 如对本篇的一些预备知识需详尽了解,可参考以上两篇. Javascript 有提供Dat ...

  7. extjs 月份选择控件_Ext JS 4实现带week(星期)的日期选择控件(实战二)

    前言 JavaScript 中的日期和时间 Ext JS 4实现带week(星期)的日期选择控件(实战一) 如对本篇的一些预备知识需详尽了解,可参考以上两篇. Javascript 有提供Date 对 ...

  8. WPF自定义LED风格数字显示控件

    WPF自定义LED风格数字显示控件 原文:WPF自定义LED风格数字显示控件 版权声明:本文为博主原创文章,转载请注明作者和出处 https://blog.csdn.net/ZZZWWWPPP1119 ...

  9. Swing的日期选择控件DatePicker

    Swing的日期选择控件 依赖的包 图片示例 示例代码段 设置日期控件的值 验证代码 结论 依赖的包 下载DatePicker.jar 图片示例 示例代码段 JLabel dateJLabel = n ...

最新文章

  1. mysql 存储过程 主键_存储过程生成主键
  2. 学好SQL--MySQL简单使用(3)
  3. 20172330 2017-2018-1 《Java程序设计》第七周学习总结
  4. rabbitmq-java生产者消费者
  5. oracle自动备份定时任务,Oracle数据库定时自动备份批处理代码(Windows)
  6. Linux 中使用 sort 指令分组排序详解
  7. bcb隐藏窗口_BCB隐藏Windows任务栏的方法
  8. css的三种引入方式 1211
  9. 【洛谷】【treap/堆】P2073 送花
  10. 电容屏、电阻屏基础知识
  11. wh计算公式_锂电池计算公式wh 锂电池的mah和wh如何换算?
  12. Axure学习笔记整理5-灯箱效果
  13. zz淘宝笑到喷的评价
  14. 基于Python的深度神经网络的中文期刊分类系统
  15. Java大牛呕心沥血经历——技术面试与HR谈薪资技巧...
  16. overload override
  17. 删除线性表节点(线性表)
  18. 微信小程序--注册、接入流程
  19. 前端周报:最经典的26个JavaScript面试题和答案;Vue3.0
  20. 手把手教你重装系统,新手必看,最全教程

热门文章

  1. 如今黑帽查找引擎优化的难点
  2. ZigBee On Windows Mobile-ZigBee模块的设计制作
  3. 小試正則表達式(必須包括數字,定量字符,字母)
  4. springboot 使用webflux响应式开发教程(二)
  5. win10系统下安装Linux虚拟机以及在虚拟机上安装Ubuntu
  6. 利用mysql5.6 的st_distance 实现按照距离远近排序。 (转载)
  7. 手机摇一摇功能音量大小跟系统音量一致
  8. Storm介绍及核心组件和编程模型
  9. xm list源码分析
  10. 建设工程安全生产管理条例