900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

时间:2019-09-03 22:56:14

相关推荐

WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

原文:WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

一.前言

申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接。

本文主要内容:

日历控件Calendar自定义样式; 日期控件DatePicker自定义样式,及Label标签、水印、清除日期功能扩展;

二.Calendar自定义样式

先看看效果:

从上面图可以看出,日历的显示其实有三种状态,如下面的分解图:

"日"部分的显示; "月"部分的显示; "年"部分的显示;

因此一个完整的日历,就包含多个部分,首先是"日"按钮的样式:

<!--Day按钮样式--><Style x:Key="CalendarDayButtonStyle" TargetType="{x:Type CalendarDayButton}"><Setter Property="MinWidth" Value="28" /><Setter Property="MinHeight" Value="5" /><Setter Property="FontFamily" Value="{StaticResource FontFamily}" /><Setter Property="HorizontalContentAlignment" Value="Center" /><Setter Property="VerticalContentAlignment" Value="Center" /><Setter Property="Background" Value="Transparent" /><Setter Property="Foreground" Value="{StaticResource TextForeground}" /><Setter Property="Margin" Value="0" /><Setter Property="IsTabStop" Value="False" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type CalendarDayButton}"><Grid x:Name="Grid" Margin="{TemplateBinding Margin}"><Border x:Name="Bg" Background="{TemplateBinding Background}" /><ContentPresenter x:Name="NormalText" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"Margin="5,2,5,2" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"TextElement.Foreground="{TemplateBinding Foreground}" /></Grid><ControlTemplate.Triggers><Trigger Property="IsSelected" Value="True"><Setter Property="Background" Value="{StaticResource ItemSelectedBackground}"></Setter><Setter Property="Foreground" Value="{StaticResource ItemSelectedForeground}"></Setter></Trigger><Trigger Property="IsToday" Value="True"><Setter Property="Background" Value="{StaticResource ItemHighlighteBackground}"></Setter><Setter Property="Foreground" Value="{StaticResource ItemHighlighteForeground}"></Setter></Trigger><Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="{StaticResource ItemMouseOverBackground}"></Setter><Setter Property="Foreground" Value="{StaticResource ItemMouseOverForeground}"></Setter></Trigger><!--不可用日期--><Trigger Property="IsBlackedOut" Value="True"><Setter Property="Opacity" Value="{StaticResource DisableOpacity}" TargetName="Grid"></Setter></Trigger><!--不在当月的日期--><Trigger Property="IsInactive" Value="True"><Setter Property="Opacity" Value="0.65" TargetName="Grid"></Setter></Trigger><Trigger Property="IsEnabled" Value="False"><Setter Property="Opacity" Value="{StaticResource DisableOpacity}" TargetName="Grid"></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>

View Code

日历日期面板样式:

<!--日历日期面板样式--><Style x:Key="CalendarItemStyle" TargetType="{x:Type CalendarItem}"><Setter Property="Margin" Value="0,1,0,1" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type CalendarItem}"><ControlTemplate.Resources><!-- 头部星期样式--><DataTemplate x:Key="{x:Static CalendarItem.DayTitleTemplateResourceKey}"><TextBlock Text="{Binding}" FontWeight="Bold" FontFamily="{StaticResource FontFamily}" Foreground="{StaticResource PressedForeground}"FontSize="{StaticResource HeaderFontSize}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,6,0,6" Opacity="0.8" /></DataTemplate></ControlTemplate.Resources><Grid x:Name="PART_Root"><Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" Background="{TemplateBinding Background}" Margin="{TemplateBinding Margin}"><Grid Margin="2"><Grid.ColumnDefinitions><ColumnDefinition Width="Auto" /></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="Auto" /><RowDefinition Height="*" /></Grid.RowDefinitions><!--Header--><Grid Grid.Row="0" HorizontalAlignment="Stretch" Background="{StaticResource HeaderBackground}"><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="2*"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><local:FButton x:Name="PART_HeaderButton" FontWeight="Bold" Style="{StaticResource FButton_Transparency}"Focusable="False" Grid.Column="1" FIcon="{x:Null}"/><local:FButton x:Name="PART_PreviousButton" Style="{StaticResource FButton_Transparency}"Focusable="False" Grid.Column="0" FIconSize="18" Content="" FIcon="&#xe65e;"/><local:FButton x:Name="PART_NextButton" Style="{StaticResource FButton_Transparency}"Focusable="False" Grid.Column="2" FIconSize="18" Content="" FIcon="&#xe605;"/></Grid><!--PART_MonthView--><Grid x:Name="PART_MonthView" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="6,1,6,6" Grid.Row="1" Visibility="Visible"><Grid.ColumnDefinitions><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="*" /><RowDefinition Height="*" /><RowDefinition Height="*" /><RowDefinition Height="*" /><RowDefinition Height="*" /><RowDefinition Height="*" /><RowDefinition Height="*" /></Grid.RowDefinitions></Grid><!--PART_YearView--><Grid x:Name="PART_YearView" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="6,10,6,10" Grid.Row="1" Visibility="Hidden"><Grid.ColumnDefinitions><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="*" /><RowDefinition Height="*" /><RowDefinition Height="*" /></Grid.RowDefinitions></Grid></Grid></Border></Grid><ControlTemplate.Triggers><Trigger Property="IsEnabled" Value="False"><Setter Property="Opacity" TargetName="PART_Root" Value="{StaticResource DisableOpacity}" /></Trigger><DataTrigger Binding="{Binding DisplayMode, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}}" Value="Year"><Setter Property="Visibility" TargetName="PART_MonthView" Value="Hidden" /><Setter Property="Visibility" TargetName="PART_YearView" Value="Visible" /></DataTrigger><!--Decade 美 ['dɛked] n. 十年,十年期;十--><DataTrigger Binding="{Binding DisplayMode, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}}" Value="Decade"><Setter Property="Visibility" TargetName="PART_MonthView" Value="Hidden" /><Setter Property="Visibility" TargetName="PART_YearView" Value="Visible" /></DataTrigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>

View Code

年月按钮样式:

<!--年、月按钮样式--><Style x:Key="CalendarButtonStyle" TargetType="{x:Type CalendarButton}"><Setter Property="Background" Value="Transparent" /><Setter Property="MinWidth" Value="40" /><Setter Property="MinHeight" Value="42" /><Setter Property="FontSize" Value="{StaticResource FontSize}" /><Setter Property="FontFamily" Value="{StaticResource FontFamily}" /><Setter Property="HorizontalContentAlignment" Value="Center" /><Setter Property="VerticalContentAlignment" Value="Center" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type CalendarButton}"><Grid x:Name="Grid" Margin="{TemplateBinding Margin}"><Border x:Name="Bg" Background="{TemplateBinding Background}" /><ContentPresenter x:Name="NormalText" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"Margin="5,2,5,2" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"TextElement.Foreground="{TemplateBinding Foreground}" /></Grid><ControlTemplate.Triggers><Trigger Property="IsFocused" Value="True"><Setter Property="Background" Value="{StaticResource ItemSelectedBackground}"></Setter><Setter Property="Foreground" Value="{StaticResource ItemSelectedForeground}"></Setter></Trigger><Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="{StaticResource ItemMouseOverBackground}"></Setter><Setter Property="Foreground" Value="{StaticResource ItemMouseOverForeground}"></Setter></Trigger><!--不在当月的日期--><Trigger Property="IsInactive" Value="True"><Setter Property="Opacity" Value="0.8" TargetName="Grid"></Setter></Trigger><Trigger Property="IsEnabled" Value="False"><Setter Property="Opacity" Value="{StaticResource DisableOpacity}" TargetName="Grid"></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>

View Code

最后综合以上的样式,定义我们需要的Calendar样式就差一步之遥了。

<!--默认日历样式--><Style x:Key="DefaultCalendar" TargetType="{x:Type Calendar}"><Setter Property="SnapsToDevicePixels" Value="True" /><Setter Property="Foreground" Value="{StaticResource TextForeground}" /><Setter Property="CalendarDayButtonStyle" Value="{StaticResource CalendarDayButtonStyle}" /><Setter Property="CalendarItemStyle" Value="{StaticResource CalendarItemStyle}" /><Setter Property="CalendarButtonStyle" Value="{StaticResource CalendarButtonStyle}" /><Setter Property="Background" Value="{StaticResource PopupBackground}" /><Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" /><Setter Property="BorderThickness" Value="1" /><Setter Property="FontSize" Value="13" /><Setter Property="FontFamily" Value="{StaticResource FontFamily}" /><Setter Property="IsTodayHighlighted" Value="True" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Calendar}"><StackPanel x:Name="PART_Root" HorizontalAlignment="Center" Background="Transparent"><CalendarItem x:Name="PART_CalendarItem" BorderBrush="{TemplateBinding BorderBrush}" FontSize="{TemplateBinding FontSize}"FontFamily="{TemplateBinding FontFamily}"BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"Style="{TemplateBinding CalendarItemStyle}" /></StackPanel></ControlTemplate></Setter.Value></Setter></Style>

三.DatePicker自定义样式,及Label标签、水印、清除日期功能扩展

有了上面的日历样式,下面做DatePicker的样式就好办了,其实就是TextBox+Button+Calendar。此处的实现同上一篇(WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式)思路基本一致,因此本文就不做更多的解释,可以参考本系列前面的文章(末尾附录有链接)先看看效果图:

3.1 DatePicker自定义样式

基本样式定义:

<Style x:Key="DefaultDatePicker" TargetType="{x:Type DatePicker}"><Setter Property="Foreground" Value="{StaticResource TextForeground}" /><Setter Property="Background" Value="{StaticResource TextBackground}" /><Setter Property="BorderThickness" Value="1" /><Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" /><Setter Property="local:ControlAttachProperty.FocusBorderBrush" Value="{StaticResource FocusBorderBrush}" /><Setter Property="local:ControlAttachProperty.MouseOverBorderBrush" Value="{StaticResource MouseOverBorderBrush}" /><Setter Property="local:ControlAttachProperty.FIconSize" Value="21" /><Setter Property="FontFamily" Value="{StaticResource FontFamily}" /><Setter Property="FontSize" Value="{StaticResource FontSize}" /><Setter Property="MinHeight" Value="26" /><Setter Property="Height" Value="30" /><Setter Property="Width" Value="200" /><Setter Property="HorizontalContentAlignment" Value="Stretch" /><Setter Property="IsTodayHighlighted" Value="True" /><Setter Property="Padding" Value="0" /><Setter Property="Margin" Value="0" /><Setter Property="SelectedDate" Value="{x:Null}" /><Setter Property="SnapsToDevicePixels" Value="True" /><Setter Property="CalendarStyle" Value="{StaticResource DefaultCalendar}" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type DatePicker}"><Grid x:Name="PART_Root"><Border x:Name="Bg" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"Background="{TemplateBinding Background}" /><Grid x:Name="PART_InnerGrid" Margin="0"><Grid.ColumnDefinitions><ColumnDefinition Width="Auto" /><ColumnDefinition Width="*" /><ColumnDefinition Width="Auto" /><ColumnDefinition Width="Auto" /></Grid.ColumnDefinitions><!--Label区域--><ContentControl x:Name="Label" Template="{TemplateBinding local:ControlAttachProperty.LabelTemplate}" IsTabStop="False" IsHitTestVisible="False"Content="{TemplateBinding local:ControlAttachProperty.Label}" Margin="1,1,0,1"/><!--附加内容区域--><Border x:Name="PART_AttachContent" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center" ><ContentControl VerticalAlignment="Center" VerticalContentAlignment="Center" Template="{TemplateBinding local:ControlAttachProperty.AttachContent}"/></Border><!--下拉按钮--><ToggleButton x:Name="PART_DropDownToggle" IsTabStop="False" Style="{StaticResource FIconToggleButton}" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1,1,3,1"Grid.Column="3" local:ControlAttachProperty.FIconSize="{TemplateBinding local:ControlAttachProperty.FIconSize}"Background="{TemplateBinding local:ControlAttachProperty.FocusBackground}"/><!--水印--><Border Grid.Column="1"><TextBlock x:Name="Message" Padding="0" Visibility="Collapsed" Text="{TemplateBinding local:ControlAttachProperty.Watermark}" Foreground="{TemplateBinding Foreground}" IsHitTestVisible="False" Opacity="{StaticResource WatermarkOpacity}" HorizontalAlignment="Left" TextAlignment="Center" VerticalAlignment="Center" Margin="5,2,5,2" /></Border><!--Date内容区--><Grid Grid.Column="1"><TextBox x:Name="PART_TextBox" Style="{StaticResource EditableTextBoxStyle}" HorizontalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" IsHitTestVisible="True" IsReadOnly="True"FontFamily="{TemplateBinding FontFamily}" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" Text="{Binding Path=SelectedDate,Mode=OneWay,RelativeSource={RelativeSource TemplatedParent},StringFormat={StaticResource DateFormat}}"/></Grid><!--弹出日历--><Popup x:Name="PART_Popup" AllowsTransparency="True" Placement="Bottom"PlacementTarget="{Binding ElementName=PART_Root}" StaysOpen="False" /></Grid></Grid><ControlTemplate.Triggers><!--1.显示水印--><DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value=""><Setter TargetName="Message" Property="Visibility" Value="Visible" /></DataTrigger><Trigger Property="IsMouseOver" Value="True"><Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.MouseOverBorderBrush),RelativeSource={RelativeSource Self}}"/></Trigger><Trigger Property="IsFocused" Value="True"><Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/></Trigger><Trigger Property="IsKeyboardFocusWithin" Value="True"><Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/></Trigger><Trigger Property="IsEnabled" Value="False"><Setter TargetName="PART_Root" Property="Opacity" Value="{StaticResource DisableOpacity}" /></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>

View Code

水印效果:

使用示例:

<DatePicker Margin="3" core:ControlAttachProperty.Watermark="妈的快输入日期"/><DatePicker Margin="3" SelectedDate="{x:Static system:DateTime.Today}"/><DatePicker Margin="3" IsEnabled="False" SelectedDate="{x:Static system:DateTime.Today}"/>

3.2 Label标签

通过扩展基础样式中的标签附加属性实现,定义样式代码:

<!--DatePicker包含附加属性Label的样式 LabelDatePicker --><Style TargetType="{x:Type DatePicker}" x:Key="LabelDatePicker" BasedOn="{StaticResource DefaultDatePicker}"><Setter Property="Width" Value="260"></Setter><Setter Property="local:ControlAttachProperty.LabelTemplate" ><Setter.Value><ControlTemplate TargetType="ContentControl"><Border Width="60" Background="{StaticResource TextLabelBackground}"><TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="2" Text="{TemplateBinding Content}"></TextBlock></Border></ControlTemplate></Setter.Value></Setter></Style>

效果图:

使用示例:

<DatePicker Margin="3" Style="{StaticResource LabelClearButtonDatePicker}" core:ControlAttachProperty.Watermark="选择出生日期" core:ControlAttachProperty.Label="出生日期"/><DatePicker Margin="3" Style="{StaticResource LabelDatePicker}" core:ControlAttachProperty.Label="死亡日期" SelectedDate="{x:Static system:DateTime.Today}"/><DatePicker Margin="3" Style="{StaticResource LabelDatePicker}" core:ControlAttachProperty.Label="非法日期" IsEnabled="False" SelectedDate="{x:Static system:DateTime.Today}"/>

3.3 清除日期值的功能扩展

此功能在前面的文章有介绍过(参考本文末尾链接),效果在上面的图片中可以看到。样式代码:

<!--DatePicker包含清除Text按钮的样式 ClearButtonDatePicker --><Style TargetType="{x:Type DatePicker}" x:Key="ClearButtonDatePicker" BasedOn="{StaticResource DefaultDatePicker}"><Setter Property="local:ControlAttachProperty.AttachContent"><Setter.Value><ControlTemplate><local:FButton FIcon="&#xe60a;" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"local:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.ClearTextCommand" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DatePicker}}}"Margin="1,3,0,4" FIconSize="14" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/></ControlTemplate></Setter.Value></Setter></Style><!--DatePicker包含附加属性Label,以及ClearText按钮的样式 LabelClearButtonDatePicker --><Style TargetType="{x:Type DatePicker}" x:Key="LabelClearButtonDatePicker" BasedOn="{StaticResource DefaultDatePicker}"><Setter Property="Width" Value="280"></Setter><Setter Property="local:ControlAttachProperty.LabelTemplate" ><Setter.Value><ControlTemplate TargetType="ContentControl"><Border Width="60" Background="{StaticResource TextLabelBackground}"><TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="2" Text="{TemplateBinding Content}"></TextBlock></Border></ControlTemplate></Setter.Value></Setter><Setter Property="local:ControlAttachProperty.AttachContent"><Setter.Value><ControlTemplate><local:FButton FIcon="&#xe60a;" Style="{StaticResource FButton_Transparency}" IsTabStop="False" FIconMargin="0"local:ControlAttachProperty.IsClearTextButtonBehaviorEnabled="True" Command="local:ControlAttachProperty.ClearTextCommand" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DatePicker}}}"Margin="0,3,0,4" FIconSize="14" Foreground="{StaticResource TextForeground}" Cursor="Arrow"/></ControlTemplate></Setter.Value></Setter></Style>

使用示例:

<DatePicker Margin="3" Style="{StaticResource ClearButtonDatePicker}"/><DatePicker Margin="3" Style="{StaticResource LabelClearButtonDatePicker}" core:ControlAttachProperty.Watermark="选择出生日期" core:ControlAttachProperty.Label="出生日期"/>

附录:参考引用

WPF自定义控件与样式(1)-矢量字体图标(iconfont)

WPF自定义控件与样式(2)-自定义按钮FButton

WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展

WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式

版权所有,文章来源:/anding

个人能力有限,本文内容仅供学习、探讨,欢迎指正、交流。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。