wpf日历控件制作过程分析(全)[转]

希望通过分析能更好的理解wpf控件的开发

wpf日历控件制作过程分析(1)---定义header

一.日历的header布局

包含两部分,两个按钮和一个Title

wpf日历控件制作过程分析(1)---定义header

首先定义按钮的样式(随自己定),可以先定义几个状态为普通状态,鼠标经过状态,按下状态和禁用4个状态显示不同的样式.其中按钮上还有一个小三角.所以还要定义一个三角的Geometry

代码开始

1.画出Geometry(涉及知识点为Geometry的画法及迷你语法,如M Z等)

2.定义4个不同状态下的笔刷(可自由发挥)

Code































3.定义按钮样式,按钮上再使用上面的笔刷

Code


注意上面黑字,这里使用了数据绑定的类型转换器,只要给这个控件指定数据源就可以了,其作用是把日期转换上面第二张截图的格式

5.整合header

Code





Margin="7 5 0 0" HorizontalAlignment="Left" >









Margin="0 5 7 0" HorizontalAlignment="Right">









注意点:

1.使用DataContext作为数据源

2.用RepeatButton当作按钮(可重复触发事件)

3.使用LayoutTransform翻转Geometry图形

4.自定义样式TitleStyle,默认为空

5.未见RepeatButton使用定义的ButtonBase样式?(可与第四点比较)

下次继续

定义header

在header中,我们看到了定义一个自定义样式TitleStyle

1.自定义样式

看后台代码定义

Code

/**


/// The DependencyProperty for the TitleStyle property.
/// Flags: none
/// Default Value: null
///

public static readonly DependencyProperty TitleStyleProperty =
DependencyProperty.Register(
"TitleStyle",
typeof(Style),
typeof(MonthCalendar),
new FrameworkPropertyMetadata(
(Style)null));
/**
/// TitleStyle property
///

public Style TitleStyle
{
get { return (Style)GetValue(TitleStyleProperty); }
set { SetValue(TitleStyleProperty, value); }
}

应该说,是比较简单的,默认样式为null,如果指定了样式的话,则会覆盖默认的样式

2.不重叠选择样式

为日历的前进和后退按钮定义两个样式

Code

/**


/// The DependencyProperty for the PreviousButtonStyle property.
/// Flags: none
/// Default Value: null
///

public static readonly DependencyProperty PreviousButtonStyleProperty =
DependencyProperty.Register(
"PreviousButtonStyle",
typeof(Style),
typeof(MonthCalendar),
new FrameworkPropertyMetadata(
(Style)null, new PropertyChangedCallback(OnPreviousButtonStyleChanged)));
/**
/// PreviousButtonStyle property
///

public Style PreviousButtonStyle
{
get { return (Style)GetValue(PreviousButtonStyleProperty); }
set { SetValue(PreviousButtonStyleProperty, value); }
}
private static void OnPreviousButtonStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MonthCalendar)d).RefreshPreviousButtonStyle();
}
/**
/// The DependencyProperty for the NextButtonStyle property.
/// Flags: none
/// Default Value: null
///

public static readonly DependencyProperty NextButtonStyleProperty =
DependencyProperty.Register(
"NextButtonStyle",
typeof(Style),
typeof(MonthCalendar),
new FrameworkPropertyMetadata(
(Style)null, new PropertyChangedCallback(OnNextButtonStyleChanged)));
/**
/// NextButtonStyle property
///

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方法中调用













DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=0,RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/>

DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=1, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/>

DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=2, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/>

DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=3, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/>

DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=4, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/>

DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=5, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/>

DataContext="{Binding Path=FirstDayOfWeek,Mode=OneWay,Converter={StaticResource MonthCalendarDayHeaderConverter},ConverterParameter=6, RelativeSource={RelativeSource AncestorType={x:Type DateControls:MonthCalendar}}}"/>

FirstDayOfWeek属性类型为DayOfWeek 枚举,通过数据绑定的ConverterParameter属性传递参数,然后通过类型转换器转换数据

然后再画一条分隔线

到目前为止,默认的显示效果如下

wpf日历控件制作过程分析(3)---定义DayHeaders

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值