CalendarDayButtonStyle:
<Style x:Key="CalendarDayButtonStyle1" targettype="System_Windows_Controls_Primitives:CalendarDayButton"> <Setter Property="Background" Value="#FFBADDE9" /> <Setter Property="FontSize" Value="10" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="MinWidth" Value="5" /> <Setter Property="MinHeight" Value="5" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate targettype="System_Windows_Controls_Primitives:CalendarDayButton"> <Grid> <visualstatemanager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0:0:0.1" /> </VisualStateGroup.Transitions> <VisualState x:Name="normal" /> <VisualState x:Name="MouSEOver"> <Storyboard> <DoubleAnimation Duration="0" To=".5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Background" /> </Storyboard> </VisualState> <VisualState x:Name="pressed"> <Storyboard> <DoubleAnimation Duration="0" To=".5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Background" /> </Storyboard> </VisualState> <VisualState x:Name="disabled"> <Storyboard> <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Background" /> <DoubleAnimation Duration="0" To=".35" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Content" /> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="SelectionStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0" /> </VisualStateGroup.Transitions> <VisualState x:Name="Unselected" /> <VisualState x:Name="Selected"> <Storyboard> <DoubleAnimation Duration="0" To=".75" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBackground" /> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="CalendarButtonFocusstates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0" /> </VisualStateGroup.Transitions> <VisualState x:Name="CalendarButtonFocused"> <Storyboard> <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisual"> <discreteObjectKeyFrame KeyTime="0" Value="Visible" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="CalendarButtonUnfocused"> <Storyboard> <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisual"> <discreteObjectKeyFrame KeyTime="0" Value="Collapsed" /> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="ActiveStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0" /> </VisualStateGroup.Transitions> <VisualState x:Name="Active" /> <VisualState x:Name="Inactive"> <Storyboard> <ColorAnimation Duration="0" To="#FF777777" Storyboard.TargetProperty="(ContentControl.Foreground).(GradientBrush.GradientStops)[2].(GradientStop.Color)" Storyboard.TargetName="Content" /> <ColorAnimation Duration="0" To="#FF777777" Storyboard.TargetProperty="(ContentControl.Foreground).(GradientBrush.GradientStops)[3].(GradientStop.Color)" Storyboard.TargetName="Content" /> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="DayStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0" /> </VisualStateGroup.Transitions> <VisualState x:Name="RegularDay" /> <VisualState x:Name="Today"> <Storyboard> <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="TodayBackground" /> <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(ContentControl.Foreground).(GradientBrush.GradientStops)[1].(GradientStop.Offset)" Storyboard.TargetName="Content" /> <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(ContentControl.Foreground).(GradientBrush.GradientStops)[2].(GradientStop.Offset)" Storyboard.TargetName="Content" /> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="BlackoutDayStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0" /> </VisualStateGroup.Transitions> <VisualState x:Name="normalDay" /> <VisualState x:Name="BlackoutDay"> <Storyboard> <DoubleAnimation Duration="0" To=".2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BlackoutVisual" /> </Storyboard> </VisualState> </VisualStateGroup> </visualstatemanager.VisualStateGroups> <Rectangle x:Name="TodayBackground" Fill="#FFAAAAAA" Opacity="0" RadiusY="1" RadiusX="1" /> <Rectangle x:Name="SelectedBackground" Fill="{TemplateBinding Background}" Opacity="0" RadiusY="1" RadiusX="1" /> <Rectangle x:Name="Background" Fill="{TemplateBinding Background}" Opacity="0" RadiusY="1" RadiusX="1" /> <ContentControl x:Name="Content" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsTabStop="False" Margin="5,1,5,1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Style="{StaticResource ContentControlStyle1}"> <ContentControl.Foreground> <LinearGradientBrush> <GradientStop Color="#FFFFFFFF" Offset="0" /> <GradientStop Color="#FFFFFFFF" Offset="0" /> <GradientStop Color="#FF333333" Offset="0" /> <GradientStop Color="#FF333333" Offset="1" /> </LinearGradientBrush> </ContentControl.Foreground> </ContentControl> <Path x:Name="BlackoutVisual" Data="M8.1772461,11.029181 L10.433105,11.029181 L11.700684,12.801641 L12.973633,11.029181 L15.191895,11.029181 L12.844727,13.999395 L15.21875,17.060919 L12.962891,17.060919 L11.673828,15.256231 L10.352539,17.060919 L8.1396484,17.060919 L10.519043,14.042364 z" Fill="#FF000000" HorizontalAlignment="Stretch" Margin="3" Opacity="0" RenderTransformOrigin="0.5,0.5" Stretch="Fill" VerticalAlignment="Stretch" /> <Rectangle x:Name="FocusVisual" IsHitTestVisible="false" RadiusY="1" RadiusX="1" stroke="#FF6DBDD1" Visibility="Collapsed" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
这次先看看折叠版:
只有ContentControl是需要关注的核心,再看下Blend中的视图
注意到content的datacontext属性,不再是集成的Calendar,而是DateTime!也就是每一格的日期!而且至今我仍未有找到这个格子可绑定Observable<>属性的Source。
因为格子里既有原生的日期,也有需要自定义的部分,所以我们将Content用另一个模板加载:
<Style x:Key="ContentControlStyle1" targettype="ContentControl"> <Setter Property="Foreground" Value="#FF000000" /> <Setter Property="HorizontalContentAlignment" Value="Left" /> <Setter Property="VerticalContentAlignment" Value="Top" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate targettype="ContentControl"> <Grid> <Grid.RowDeFinitions> <RowDeFinition Height="Auto"></RowDeFinition> <RowDeFinition Height="*"></RowDeFinition> </Grid.RowDeFinitions> <ContentPresenter Cursor="{TemplateBinding Cursor}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"> <TextBlock FontFamily="Georgia" FontSize="15" Text="{TemplateBinding Content}"></TextBlock> </ContentPresenter> <TextBlock Grid.Row="1" FontSize="8.5" Foreground="#aa161616"> <TextBlock.Text> <Binding Converter="{StaticResource LunaDateConverter}"/> </TextBlock.Text> </TextBlock> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
这个模板定义了content的样式,同时,利用一个ValueConverter实现了公历日期(DataContext)向农历日期的转换。
本来这样也就OK了,可用ValueConverter的时候只有一个日期参数,有时我们需要相同的日期显示不同的内容,例如不同的班组会有不同的班次安排等。
自然的,一开始便想用ConverterParameter将viewmodel实例作为参数传进去,例如:
<TextBlock Grid.Row="1" FontSize="8.5" Text='{Binding Converter={StaticResource DatetoShiftContentConverter},ConverterParameter={Binding DataContext},Mode=OneWay}' Foreground="#aa161616"/>
但正如我之前所言,DayButton的Content绑定的DataContext不再是继承于Calendar,而是当前格子的日期,因此此处的Binding是找不到通向viewmodel的路径的。后来我想用TemplateBinding尝试将viewmodel从父级一层层传下来(如利用Tag属性)但还是无法找到父级,获取到的一直是null,终究作罢:
<TextBlock Grid.Row="1" FontSize="8.5" Text='{Binding Converter={StaticResource DatetoShiftContentConverter},ConverterParameter={TemplateBinding Tag},Mode=OneWay}' Foreground="#aa161616"/>
期间我在网上各种查资料,试图设法将属性绑定到DayButton上,比如Josh Smith的 Attaching a Virtual Branch to the Logical Tree in WPF 就是一种通过所谓“逻辑树虚拟枝”技术将viewmodel间接保存下来供任意内容读取。但实现有点略复杂,试了试也没调好,遂作罢,但这篇文章给了我很好的思路。
最后,我通过ValueConverter的声明想到,可以尝试通过一个中间的静态资源实现viewmodel的传递:
<UserControl.Resources> <viewmodelConverter:DatetoShiftContentConverter x:Key='DatetoShiftContentConverter' /> <viewmodel:CalendarMonthviewmodel x:Key='CalendarMonthviewmodel' /> ...... </UserControl.Resources>
<UserControl.DataContext> <Binding Source='{StaticResource CalendarMonthviewmodel}' /> </UserControl.DataContext>
<TextBlock Grid.Row="1" FontSize="8.5" Foreground="#aa161616" Text='{Binding Converter={StaticResource DatetoShiftContentConverter},ConverterParameter={StaticResource CalendarMonthviewmodel},Mode=OneWay}' FontFamily="Microsoft YaHei" />
如此,就完美解决的参数的传递问题。
在对Calendar个性化设置的路上,虽然走了不少弯路,但最终实现了功能的同时,自己对Xaml和Wpf的一些特性有了更深入的了解和学习。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。