本文通过自定义calendar的开发,通过分析Silverlight自带的Calendar的样式、模板的分析,实现日历的定制化开发。
WPF中,自带的Calendar控件是这样子的:
而我们想要的结果是这样子的:
这个控件有两种方法去做。
一个是自己重新绘制图形,用一个7*6的表格来放日期,再根据当前月第一天的星期,计算出第一行第一列的日期,然后依次填充即可。详情可参考 Kelly Elias的这篇文章An Editable WPF Calendar Control,但这个控件其中用到了很重要的一个类UniformGrid在Silverlight中是没有的,需要自己重写,不要急,Jeff Wilco在博文UniformGrid for Silverlight中提供了解决方案。
另一个则是基于自带的Calendar,利用XAML强大的样式(Style)和模板(Template)功能完成扩展,也就是今天要讲的。
第一种方式实现简单容易扩展,可快速满足各种需求。但是功能太少,一些基本的日历功能都需要重写,比如月份更换、日期选择和反选等等。相反,第二种因为是基于自带的Calendar,不用引用过多的外部资源,即可拥有许多强大的功能,还能和其他控件融为一体等等。所以不用说,肯定用第二种的好。
关于Calendar的样式和模板,MSDN给了完整的示例。本文也是基于官方示例和非官方英文文献撰写。
首先,创建一个控件,添加一个UserControl:
<Grid x:Name="LayoutRoot"
Background="White">
<Viewbox>
<sdk:Calendar Name='calendar1' />
</Viewbox>
</Grid>
其中,ViewBox是用来实现Calendar自适应大小的。
一个Calendar可设置的样式包括Style、CalendarItemStyle、CalendarButtonStyle和CalendarDayButtonStyle
Style是用来设置Calendar整体的样式:
<Style x:Key="CalendarStyle1"
TargetType="sdk:Calendar">
<Setter Property="IsTabStop"
Value="False" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="#FFD3DEE8"
Offset="0" />
<GradientStop Color="#FFD3DEE8"
Offset="0.16" />
<GradientStop Color="#FFFCFCFD"
Offset="0.16" />
<GradientStop Color="#FFFFFFFF"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
--------------------------------------------------------------------------------------------------------------------------
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:Calendar">
<Grid x:Name="Root"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<System_Windows_Controls_Primitives:CalendarItem VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
x:Name="CalendarItem"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{Te