【C#】wpf自定义calendar日期选择控件的样式
原文:【C#】wpf自定义calendar日期选择控件的样式
首先上图,看下样式
原理
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="<" 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=">" 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="<" 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=">" 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日期选择控件的样式的更多相关文章
- Android自定义View(RollWeekView-炫酷的星期日期选择控件)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/53420889 本文出自:[openXu的博客] 目录: 1分析 2定义控件布局 3定义Cus ...
- 用c/c++混合编程方式为ios/android实现一个自绘日期选择控件(一)
本文为原创,如有转载,请注明出处:http://www.cnblogs.com/jackybu 前言 章节: 1.需求描述以及c/c++实现日期和月历的基本操作 2.ios实现自绘日期选择控件 3.a ...
- ASP.NET(c#) 日期选择控件的另一种实现方法
这篇文章是在一个英文网站发现的,完全使用ASP.NET实现了日期选择的基本功能,没有使用js,原文链接http://geekswithblogs.net/plundberg/archive/2009/ ...
- asp.net中的时间日期选择控件
asp.net中的时间日期选择控件 Posted on 2008-07-17 17:37 飛雪飄寒 阅读(22922) 评论(6) 编辑 收藏 在系统中经常需要进行时间日期选择(比如查询时间范 ...
- C# 中带有中国农历的日期选择控件
开源一款自己刚开始接触 C# 时开发的带有农历信息的日期选择控件,记得那时还是在2010年的寒假期间做的这个东西.刚开始接触 C# 时,使用WinForm来开发桌面程序,觉得简直是简单又迅速,由于 C ...
- ExtJS6.0扩展日期选择控件为也可以选择时间
PS:ExtJS自带的日期选择控件只能够选择日期,但是现在的需求需要精确到秒,所以在网上搜索了一些例子(大部分是4.0的)作为参考,然后改出了6.0可用的一个日期时间选择控件. 1.找到extjs6. ...
- js 跨域的问题 (同一个主域名不同的二级域名下的跨域问题) 解决 WdatePicker.js my97日期选择控件
例如域名是 a.xx.com 和 b.xx.com 如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain. 如果iframe的时候 a包含b 为 ...
- JQuery好用的日期选择控件 DatePicker
近期发现一个很好的基于JQ的前端UI日期选择控件Jquery.DatePicker.js 下载地址:jquery.DatePIcker.js 演示地址:DatePicker - 基于jQuery 1. ...
- [Ext JS 4] 实战之 带week(星期)的日期选择控件(三)
前言 在 [Ext JS 4] 实战之 带week(星期)的日期选择控件(二) 的最后,有提到一个解决方案. 不过这方案有一个条件 ==> “2. 每年的周数从(1-52), 如果超过52 周 ...
随机推荐
- ORA-00907: 缺失右括号问题整理解决
ORA-00907: 缺失右括号 前言 近期在开发过程中使用oracle数据库,在程序中进行查询数据时遇到了"ORA-00907: 缺失右括号"的问题.可是假设直接把sql语句直接 ...
- C - The C Answer (2nd Edition) - Exercise 1-6
/* Verify that the expression getchar() != EOF is 0 or 1. */ #include <stdio.h> main() { int c ...
- mysql mha高可用架构的安装
MMM无法全然地保证数据的一致性,所以MMM适用于对数据的一致性要求不是非常高.可是又想最大程度的保证业务可用性的场景对于那些对数据一致性要求非常高的业务,非常不建议採用MMM的这样的高可用性架构.那 ...
- jsvc 启动java 在linux下的实现原理
http://blog.csdn.net/raintungli/article/details/8265009 JSVC:http://commons.apache.org/proper/common ...
- 学汇编的时候可以拿IDA之类的反汇编工具辅助学习,再用gdb或者IDA动态调试,跟踪每条指令的 执行结果。都不难
作者:潘安仁链接:https://www.zhihu.com/question/40720890/answer/87926792来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- 浏览器对象模型(BOM)是什么?(体系结构+知识详解)(图片:结构)
浏览器对象模型(BOM)是什么?(体系结构+知识详解)(图片:结构) 一.总结 1.BOM操作所有和浏览器相关的东西:网页文档dom,历史记录,浏览器屏幕,浏览器信息,文档的地址url,页面的框架集. ...
- wait()、notify()、notifyAll()与线程通信方式总结
1.通过wait().notify().notifyAll()进行线程通信 线程通信的目标是使线程间能够互相发送信号.另一方面,线程通信使线程能够等待其他线程的信号.例如,线程B可以等待线程A的一个信 ...
- thinkphp5开发规范(加强复习之前的)
thinkphp5开发规范(加强复习之前的) 一.总结 一句话总结:和类相关的采用驼峰命名法:变量,函数,类,方法,属性采用驼峰命名发:数据库及文件及配置参数是小写字母加下划:常量大写加下划线 1.T ...
- PHP/HTML混写的四种方式总结
PHP/HTML混写的四种方式总结 一.总结 一句话总结: 注意点: 1.双引号里面解析变量:echo "$Content" 2.HEREDOC和NOWDOC的关系:类似于双引号包 ...
- 数组[0]和[firstobject]的区别
数组[0]和[firstobject]的区别 [0]:数组为空时回报错 [firstobject]:数组为空时回返回nil