wpf日历控件制作过程分析(全)[转]
2009-02-25 16:35
399 查看
希望通过分析能更好的理解wpf控件的开发
一.日历的header布局 包含两部分,两个按钮和一个Title
首先定义按钮的样式(随自己定),可以先定义几个状态为普通状态,鼠标经过状态,按下状态和禁用4个状态显示不同的样式.其中按钮上还有一个小三角.所以还要定义一个三角的Geometry 代码开始 1.画出Geometry(涉及知识点为Geometry的画法及迷你语法,如M Z等)
再来这个RefreshNextButtonStyle方法 Code
一.日历的header布局 包含两部分,两个按钮和一个Title
首先定义按钮的样式(随自己定),可以先定义几个状态为普通状态,鼠标经过状态,按下状态和禁用4个状态显示不同的样式.其中按钮上还有一个小三角.所以还要定义一个三角的Geometry 代码开始 1.画出Geometry(涉及知识点为Geometry的画法及迷你语法,如M Z等)
<PathGeometry x:Key="geometry" Figures="M0,0 4.5,4 9,0 5.5,0 4.5,1 3.5,0z"/>2.定义4个不同状态下的笔刷(可自由发挥) Code
<LinearGradientBrush x:Key="MonthCalendarButtonFillNormal" StartPoint="0,0" EndPoint="1,1"> <LinearGradientBrush.GradientStops> <GradientStop Color="#FFE1EAFE" Offset="0"/> <GradientStop Color="#FFC3D3FD" Offset="0.3"/> <GradientStop Color="#FFC3D3FD" Offset="0.6"/> <GradientStop Color="#FFBBCDF9" Offset="1"/> </LinearGradientBrush.GradientStops> </LinearGradientBrush> <LinearGradientBrush x:Key="MonthCalendarButtonFillHover" StartPoint="0, 0" EndPoint="1, 1"> <LinearGradientBrush.GradientStops> <GradientStop Color="#FFD6E7FF" Offset="0"/> <GradientStop Color="#FFD6E7FF" Offset="0.6"/> <GradientStop Color="#FFB9DAFB" Offset="1"/> </LinearGradientBrush.GradientStops> </LinearGradientBrush> <LinearGradientBrush x:Key="MonthCalendarButtonFillPressed" StartPoint="0, 0" EndPoint="1, 1"> <LinearGradientBrush.GradientStops> <GradientStop Color="#FF93A8D9" Offset="0"/> <GradientStop Color="#FFA5BDFB" Offset="0.3"/> <GradientStop Color="#FFA5BDFB" Offset="0.7"/> <GradientStop Color="#FFD2DEEB" Offset="1.0"/> </LinearGradientBrush.GradientStops> </LinearGradientBrush> <LinearGradientBrush x:Key="MonthCalendarButtonFillDisabled" StartPoint="0, 0" EndPoint="1, 1"> <LinearGradientBrush.GradientStops> <GradientStop Color="#FFF7F7F7" Offset="0"/> <GradientStop Color="#FFF0F0F0" Offset="0.3"/> <GradientStop Color="#FFECECEC" Offset="0.6"/> <GradientStop Color="#FFE3E3E3" Offset="1.0"/> </LinearGradientBrush.GradientStops> </LinearGradientBrush>3.定义按钮样式,按钮上再使用上面的笔刷 Code
<Style x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type DateControls:MonthCalendar},ResourceId=PreviousButtonStyleKey}" TargetType="{x:Type ButtonBase}"> <Setter Property="Width" Value="16" /> <Setter Property="Height" Value="16" /> <Setter Property="Background" Value="{StaticResource MonthCalendarButtonFillNormal}" /> <Setter Property="Foreground" Value="#FF4D6185"/> <Setter Property="Focusable" Value="false"/> <Setter Property="VerticalAlignment" Value="Top"/> </Style> <Style x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type DateControls:MonthCalendar},ResourceId=NextButtonStyleKey}" TargetType="{x:Type ButtonBase}"> <Setter Property="Width" Value="16" /> <Setter Property="Height" Value="16" /> <Setter Property="Background" Value="{StaticResource MonthCalendarButtonFillNormal}" /> <Setter Property="Foreground" Value="#FF4D6185"/> <Setter Property="Focusable" Value="false"/> <Setter Property="VerticalAlignment" Value="Top"/> </Style>注意上面黑字,这里使用了数据绑定的类型转换器,只要给这个控件指定数据源就可以了,其作用是把日期转换上面第二张截图的格式 5.整合header Code
<!--header beginer--> <Grid x:Name="Title"> <DateControls:MonthCalendarTitle x:Name="TitleHost" DataContext="{TemplateBinding VisibleMonth}" Style="{TemplateBinding TitleStyle}"/> <RepeatButton x:Name="PART_PreviousButton" Command="DateControls:MonthCalendar.PreviousCommand" Margin="7 5 0 0" HorizontalAlignment="Left" > <Viewbox> <Path Data="{StaticResource geometry}" Fill="Black"> <Path.LayoutTransform> <RotateTransform Angle="90"/> </Path.LayoutTransform> </Path> </Viewbox> </RepeatButton> <RepeatButton x:Name="PART_NextButton" Command="DateControls:MonthCalendar.NextCommand" Margin="0 5 7 0" HorizontalAlignment="Right"> <Viewbox> <Path Data="{StaticResource geometry}" Fill="Black"> <Path.LayoutTransform> <RotateTransform Angle="-90"/> </Path.LayoutTransform> </Path> </Viewbox> </RepeatButton> </Grid> <!--heander end-->注意点: 1.使用DataContext作为数据源 2.用RepeatButton当作按钮(可重复触发事件) 3.使用LayoutTransform翻转Geometry图形 4.自定义样式TitleStyle,默认为空 5.未见RepeatButton使用定义的ButtonBase样式?(可与第四点比较) 下次继续 定义header 在header中,我们看到了定义一个自定义样式TitleStyle 1.自定义样式 看后台代码定义 Code
/**//// <summary> /// The DependencyProperty for the TitleStyle property. /// Flags: none /// Default Value: null /// </summary> public static readonly DependencyProperty TitleStyleProperty = DependencyProperty.Register( "TitleStyle", typeof(Style), typeof(MonthCalendar), new FrameworkPropertyMetadata( (Style)null)); /**//// <summary> /// TitleStyle property /// </summary> public Style TitleStyle { get { return (Style)GetValue(TitleStyleProperty); } set { SetValue(TitleStyleProperty, value); } }应该说,是比较简单的,默认样式为null,如果指定了样式的话,则会覆盖默认的样式 2.不重叠选择样式 为日历的前进和后退按钮定义两个样式 Code
/**//// <summary> /// The DependencyProperty for the PreviousButtonStyle property. /// Flags: none /// Default Value: null /// </summary> public static readonly DependencyProperty PreviousButtonStyleProperty = DependencyProperty.Register( "PreviousButtonStyle", typeof(Style), typeof(MonthCalendar), new FrameworkPropertyMetadata( (Style)null, new PropertyChangedCallback(OnPreviousButtonStyleChanged))); /**//// <summary> /// PreviousButtonStyle property /// </summary> public Style PreviousButtonStyle { get { return (Style)GetValue(PreviousButtonStyleProperty); } set { SetValue(PreviousButtonStyleProperty, value); } } private static void OnPreviousButtonStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((MonthCalendar)d).RefreshPreviousButtonStyle(); } /**//// <summary> /// The DependencyProperty for the NextButtonStyle property. /// Flags: none /// Default Value: null /// </summary> public static readonly DependencyProperty NextButtonStyleProperty = DependencyProperty.Register( "NextButtonStyle", typeof(Style), typeof(MonthCalendar), new FrameworkPropertyMetadata( (Style)null, new PropertyChangedCallback(OnNextButtonStyleChanged))); /**//// <summary> /// NextButtonStyle property /// </summary> public Style NextButtonStyle { get { return (Style)GetValue(NextButtonStyleProperty); } set { SetValue(NextButtonStyleProperty, value); } } private static void OnNextButtonStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((MonthCalendar)d).RefreshNextButtonStyle(); }
再来这个RefreshNextButtonStyle方法 Code
private void RefreshNextButtonStyle() { ButtonBase nextButton = GetTemplateChild(c_NextButtonName) as ButtonBase; if (nextButton != null) { if (NextButtonStyle == null) { if (_defaultNextButtonStyle == null) { _defaultNextButtonStyle = FindResource(new ComponentResourceKey(typeof(MonthCalendar), "NextButtonStyleKey")) as Style; } nextButton.Style = _defaultNextButtonStyle; } else { nextButton.Style = NextButtonStyle; } } }注意点: 1.GetTemplateChild可以获取到xaml中声明了key值的元素,c_NextButtonName变量就是xaml定义的key,此key应该公开给控件的使用者,可调整样式 2.用TemplatePart公开模块样式,如两个按钮的key值 [TemplatePart(Name = "PART_PreviousButton", Type = typeof(ButtonBase))] [TemplatePart(Name = "PART_NextButton", Type = typeof(ButtonBase))] 3._defaultNextButtonStyle还是从xaml去找,其目的是为了自定义样式不会与默认样式发生冲突.可以title样式比较 4.构建可视化模板需要在OnApplyTemplate方法中使用,如上面的RefreshNextButtonStyle方法必须在OnApplyTemplate方法中调用
<!--DayHeaders--> <Grid x:Name="DayHeaders" Grid.Column="1"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <DateControls:MonthCalendarDayHeader Grid.Column="0" Style="{TemplateBinding DayHeaderStyle}" DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=0,RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/> <DateControls:MonthCalendarDayHeader Grid.Column="1" Style="{TemplateBinding DayHeaderStyle}" DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=1, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/> <DateControls:MonthCalendarDayHeader Grid.Column="2" Style="{TemplateBinding DayHeaderStyle}" DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=2, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/> <DateControls:MonthCalendarDayHeader Grid.Column="3" Style="{TemplateBinding DayHeaderStyle}" DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=3, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/> <DateControls:MonthCalendarDayHeader Grid.Column="4" Style="{TemplateBinding DayHeaderStyle}" DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=4, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/> <DateControls:MonthCalendarDayHeader Grid.Column="5" Style="{TemplateBinding DayHeaderStyle}" DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=5, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/> <DateControls:MonthCalendarDayHeader Grid.Column="6" Style="{TemplateBinding DayHeaderStyle}" DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=6, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/> </Grid> <!--DayHeaders-->FirstDayOfWeek属性类型为DayOfWeek 枚举,通过数据绑定的ConverterParameter属性传递参数,然后通过类型转换器转换数据 然后再画一条分隔线
<Rectangle x:Name="DayHeadersSplitLine" Grid.Column="1" Fill="Black" Height="1" VerticalAlignment="Bottom" Margin="2,0,2,0"/>到目前为止,默认的显示效果如下
相关文章推荐
- wpf日历控件制作过程分析(全)[转]
- wpf日历控件制作过程分析(1)---定义header
- wpf日历控件制作过程分析(2)---自定义样式属性
- wpf日历控件制作过程分析(1)---定义header
- wpf日历控件制作过程分析(3)---定义DayHeaders
- wpf日历控件制作过程分析(3)---定义DayHeaders
- wpf日历控件制作过程分析(全)[转]
- wpf日历控件制作过程分析(2)---自定义样式属性
- 终于找到了一个WPF中的日历控件
- 潘鹏整理WPF(10)日历控件Calendar&&DatePicker
- WPF控件TabControl和TabItem原模板分析
- JS制作简单的日历控件【JS Date对象操作实例演示】
- WPF闪烁预警动画的控件制作及winform调用WPF控件的方法
- (WPF)360安全卫士9.0界面制作过程
- 文件数据分析制作过程【1】
- 文件数据分析制作过程【3】
- 将保存到文件中的数据重新解析到控件中过程分析
- Android系统Recovery工作原理之使用update.zip升级过程分析(一)---update.zip包的制作
- asp.net mvc signalr简单聊天室制作过程分析
- (WPF)360安全卫士9.0界面制作过程