打印

WPF制作Calendar(1)

NcCalendar.cs:   

public class NcCalendarControl : Control
    {
        #region 构造函数
        static NcCalendarControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(NcCalendarControl), new FrameworkPropertyMetadata(typeof(NcCalendarControl)));
            CommandManager.RegisterClassCommandBinding(typeof(NcCalendarControl), new CommandBinding(PreviousYear, OnPreviousYear));
            CommandManager.RegisterClassCommandBinding(typeof(NcCalendarControl), new CommandBinding(PreviousMonth, OnPreviousMonth));
            CommandManager.RegisterClassCommandBinding(typeof(NcCalendarControl), new CommandBinding(NextYear, OnNextYear));
            CommandManager.RegisterClassCommandBinding(typeof(NcCalendarControl), new CommandBinding(NextMonth, OnNextMonth));
            CommandManager.RegisterClassCommandBinding(typeof(NcCalendarControl), new CommandBinding(Today, OnToday));
        }
        public NcCalendarControl()
        {
            this.SetValue(ItemsProperty, new NcCalendar(DateTime.Now));
            Items.SelectedChanged += new EventHandler(Items_SelectedChanged);
        }
        #endregion

        #region 属性定义
        /// <summary>
        /// 本月的"周"集合
        /// </summary>
        public NcCalendar Items
        {
            get { return (NcCalendar)GetValue(ItemsProperty); }
            set { SetValue(ItemsProperty, value); }
        }
        public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(NcCalendar), typeof(NcCalendarControl), new UIPropertyMetadata(new NcCalendar(DateTime.Now)));

        #region Changeable
        /// <summary>
        /// 是否能够通过按钮改变年、月。
        /// </summary>
        public static readonly DependencyProperty ChangeableProperty = DependencyProperty.Register("Changeable", typeof(bool), typeof(NcCalendarControl), new FrameworkPropertyMetadata(true));
        /// <summary>
        /// 获取或设置Changeable
        /// </summary>
        public bool Changeable
        {
            get { return (bool)base.GetValue(NcCalendarControl.ChangeableProperty); }
            set { base.SetValue(NcCalendarControl.ChangeableProperty, value); }
        }
        #endregion

        #region ShowHeader
        /// <summary>
        /// 是否显示月历头。
        /// </summary>
        public static readonly DependencyProperty ShowHeaderProperty = DependencyProperty.Register("ShowHeader", typeof(bool), typeof(NcCalendarControl), new FrameworkPropertyMetadata(true));
        /// <summary>
        /// 获取或设置ShowHeader
        /// </summary>
        public bool ShowHeader
        {
            get { return (bool)base.GetValue(NcCalendarControl.ShowHeaderProperty); }
            set { base.SetValue(NcCalendarControl.ShowHeaderProperty, value); }
        }
        #endregion

        #region ShowWeekTitle
        /// <summary>
        /// 是否显示周标签。
        /// </summary>
        public static readonly DependencyProperty ShowWeekTitleProperty = DependencyProperty.Register("ShowWeekTitle", typeof(bool), typeof(NcCalendarControl), new FrameworkPropertyMetadata(true));
        /// <summary>
        /// 获取或设置ShowWeekTitle
        /// </summary>
        public bool ShowWeekTitle
        {
            get { return (bool)base.GetValue(NcCalendarControl.ShowWeekTitleProperty); }
            set { base.SetValue(NcCalendarControl.ShowWeekTitleProperty, value); }
        }
        #endregion

        #region CurrentDay
        /// <summary>
        /// 获取CurrentDay标识
        /// </summary>
        public static readonly DependencyPropertyKey CurrentDayPropertyKey = DependencyProperty.RegisterReadOnly("CurrentDay", typeof(DateTime), typeof(NcCalendarControl), new FrameworkPropertyMetadata(DateTime.Now.Date));
        /// <summary>
        /// 获取CurrentDay属性
        /// </summary>
        public static readonly DependencyProperty CurrentDayProperty = CurrentDayPropertyKey.DependencyProperty;
        /// <summary>
        /// 获取CurrentDay
        /// </summary>
        public DateTime CurrentDay { get { return (DateTime)base.GetValue(NcCalendarControl.CurrentDayProperty); } }
        #endregion
        #endregion

        #region 事件定义
        /// <summary>
        /// 选项改变事件。
        /// </summary>
        public static readonly RoutedEvent SelectedChangedEvent = EventManager.RegisterRoutedEvent("SelectedChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(NcCalendarControl));
        public event RoutedEventHandler SelectedChanged
        {
            add { AddHandler(SelectedChangedEvent, value); }
            remove { RemoveHandler(SelectedChangedEvent, value); }
        }
        void RaiseSelectedChangedEvent()
        {
            RoutedEventArgs args = new RoutedEventArgs(SelectedChangedEvent,this);
            RaiseEvent(args);
        }
        #endregion

        #region 命令定义
        #region PreviousYear
        /// <summary>
        /// 月历视图向前移动一年命令。
        /// </summary>
        public static RoutedUICommand PreviousYear { get { return mPreviousYear; } }
        private static RoutedUICommand mPreviousYear = new RoutedUICommand("PreviousYear", "PreviousYear", typeof(NcCalendarControl));

        private static void OnPreviousYear(object sender, ExecutedRoutedEventArgs e)
        {
            NcCalendarControl calendar = sender as NcCalendarControl;
            if (calendar == null) return;
            calendar.Items.PreviousYear();
        }
        #endregion
        #region NextYear
        /// <summary>
        /// 月历视图向后移动一年命令。
        /// </summary>
        public static RoutedUICommand NextYear { get { return mNextYear; } }
        private static RoutedUICommand mNextYear = new RoutedUICommand("NextYear", "NextYear", typeof(NcCalendarControl));

        private static void OnNextYear(object sender, ExecutedRoutedEventArgs e)
        {
            NcCalendarControl calendar = sender as NcCalendarControl;
            if (calendar == null) return;
            calendar.Items.NextYear();
        }
        #endregion
        #region PreviousMonth
        /// <summary>
        /// 月历视图向前移动一月命令。
        /// </summary>
        public static RoutedUICommand PreviousMonth { get { return mPreviousMonth; } }
        private static RoutedUICommand mPreviousMonth = new RoutedUICommand("PreviousMonth", "PreviousMonth", typeof(NcCalendarControl));

        private static void OnPreviousMonth(object sender, ExecutedRoutedEventArgs e)
        {
            NcCalendarControl calendar = sender as NcCalendarControl;
            if (calendar == null) return;
            calendar.Items.PreviousMonth();
        }
        #endregion
        #region NextMonth
        /// <summary>
        /// 月历视图向后移动一月命令。
        /// </summary>
        public static RoutedUICommand NextMonth { get { return mNextMonth; } }
        private static RoutedUICommand mNextMonth = new RoutedUICommand("NextMonth", "NextMonth", typeof(NcCalendarControl));

        private static void OnNextMonth(object sender, ExecutedRoutedEventArgs e)
        {
            NcCalendarControl calendar = sender as NcCalendarControl;
            if (calendar == null) return;
            calendar.Items.NextMonth();
        }
        #endregion
        #region Today
        /// <summary>
        /// 转到今天命令。
        /// </summary>
        public static RoutedUICommand Today { get { return mToday; } }
        private static RoutedUICommand mToday = new RoutedUICommand("Today", "Today", typeof(NcCalendarControl));
        private static void OnToday(object sender, ExecutedRoutedEventArgs e)
        {
            NcCalendarControl calendar = sender as NcCalendarControl;
            if (calendar == null) return;
            calendar.Items.Today();
            DateTime dt = calendar.CurrentDay.Date;
            // 依赖于XAML中的控件,需要改进 ??????????????????????????
            List<RadioButton> rbList = new List<RadioButton>();
            calendar.FindRadioButton(calendar, rbList);
            foreach(RadioButton one in rbList )
            {
                NcCalendarDay day = one.DataContext as NcCalendarDay;
                if (day != null && day.Value.Date == dt.Date)
                {
                    one.Focus();
                    break;
                }
            }
        }
        /// <summary>
        /// 查找视图中的“天”按钮。
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="rbList"></param>
        private void FindRadioButton(DependencyObject parent, List<RadioButton> rbList)
        {
            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                DependencyObject obj = VisualTreeHelper.GetChild(parent, i);
                if (obj.GetType() == typeof(RadioButton))
                {
                    RadioButton rb = obj as RadioButton;
                    if (rb != null) rbList.Add(rb);

                    //NcCalendarDay day = rb.Content as NcCalendarDay;
                    //if (day != null && day.Value.Date == dt.Date)
                    //{
                    //    rb.Focus();
                    //    break;
                    //}
                }
                else
                    FindRadioButton(obj, rbList);
            }

        }
        #endregion
        #endregion

        /// <summary>
        /// 设置控件的当前日期。如果日期不在当前显示的月份,当前日历视图将变为指定日期所在的月份视图。
        /// </summary>
        /// <param name="date">日期。</param>
        public void SetValue(DateTime date) { if (date != null) Items.SetValue(date); }

        /// <summary>
        /// 选项改变事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Items_SelectedChanged(object sender, EventArgs e)
        {
            if (Items.Current == null || Items.Current == NcCalendarDay.Empty) return;
            DateTime dt = Items.Current.Value;
            this.SetValue(NcCalendarControl.CurrentDayPropertyKey, dt);
            RaiseSelectedChangedEvent();
        }
    }

WPF制作Calendar(2)

Calendar.cs:

    public class NcCalendar : ObservableCollection<NcCalendarWeek>, INotifyPropertyChanged
    {
        #region 字段定义
        private int mYear;
        private int mMonth;
        private NcCalendarDay mCurrent = NcCalendarDay.Empty;

        #endregion
        #region 事件定义
        public event EventHandler SelectedChanged;
        public event EventHandler CurrentChanged;
        #endregion
        #region 构造函数
        public NcCalendar() : this(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day) { }
        public NcCalendar(DateTime date) : this(date.Year, date.Month, date.Day) { }
        public NcCalendar(int year, int month) : this(year, month, 1) { }
        public NcCalendar(int year, int month, int day) { BuildCalendar(year, month, day); }
        #endregion
        #region 属性定义
        public int Year
        {
            get { return mYear; }
            set
            {
                int day = (mCurrent != null) ? day = mCurrent.Day : 1;
                if (BuildCalendar(value, mMonth, day)) OnPropertyChanged(new PropertyChangedEventArgs("Year"));
            }
        }
        public int Month
        {
            get { return mMonth; }
            set
            {
                int day = (mCurrent != null) ? day = mCurrent.Day : 1;
                if (BuildCalendar(mYear, value, day)) OnPropertyChanged(new PropertyChangedEventArgs("Month"));
            }
        }
        public int Day
        {
            get { return mCurrent.Day; }
            set { if (BuildCalendar(mYear, mMonth, value)) OnPropertyChanged(new PropertyChangedEventArgs("Day")); }
        }

        public NcCalendarDay Current
        {
            get { return mCurrent; }
            set
            {
                if (value == null || value == NcCalendarDay.Empty || value == mCurrent || value.Value.Date == mCurrent.Value.Date) return;
                bool setOK = false;
                foreach (NcCalendarWeek week in this)
                {
                    foreach (NcCalendarDay one in week)
                    {
                        if (one.IsEmpty) continue;
                        if (one.Value.Date == value.Value.Date)
                        {
                            mCurrent = one;
                            setOK = true;
                            OnPropertyChanged(new PropertyChangedEventArgs("Day"));
                            this.OnSelectedChanged(new EventArgs());
                            break;
                        }
                    }
                    if (setOK) break;
                }
            }
        }
        #endregion

        #region 方法定义
        public void SetValue(DateTime date) { BuildCalendar(date); }
        /// <summary>
        /// 向后一年
        /// </summary>
        public void NextYear()
        {
            if (mCurrent.Year == mYear && mCurrent.Month == mMonth)
            {
                BuildCalendar(mCurrent.Value.AddYears(1));
                return;
            }

            int newYear = mYear + 1;
            int newMonth = mMonth;
            int newDay = (mCurrent==null || mCurrent == NcCalendarDay.Empty) ? DateTime.Now.Day : mCurrent.Value.Day;

            DateTime maxDate = CultureInfo.CurrentCulture.Calendar.MaxSupportedDateTime.Date;
            if (newYear > maxDate.Year) return;

            int maxMonthOfYear = CultureInfo.CurrentCulture.Calendar.GetMonthsInYear(newYear);
            if (newMonth > maxMonthOfYear) newMonth = maxMonthOfYear;
            int maxDayOfMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(newYear, newMonth);
            if (newDay > maxDayOfMonth) newDay = maxDayOfMonth;

            BuildCalendar(newYear, newMonth, newDay);
        }
        /// <summary>
        /// 向前一年
        /// </summary>
        public void PreviousYear()
        {
            if (mCurrent.Year == mYear && mCurrent.Month == mMonth)
            {
                BuildCalendar(mCurrent.Value.AddYears(-1));
                return;
            }

            int newYear = mYear - 1;
            int newMonth = mMonth;
            int newDay = (mCurrent == null || mCurrent == NcCalendarDay.Empty) ? DateTime.Now.Day : mCurrent.Value.Day;

            DateTime minDate = CultureInfo.CurrentCulture.Calendar.MinSupportedDateTime.Date;
            if (newYear < minDate.Year) return;

            int maxMonthOfYear = CultureInfo.CurrentCulture.Calendar.GetMonthsInYear(newYear);
            if (newMonth > maxMonthOfYear) newMonth = maxMonthOfYear;
            int maxDayOfMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(newYear, newMonth);
            if (newDay > maxDayOfMonth) newDay = maxDayOfMonth;

            BuildCalendar(newYear, newMonth, newDay);
        }
        /// <summary>
        /// 向后一个月
        /// </summary>
        public void NextMonth()
        {
            if (mCurrent.Year ==mYear && mCurrent.Month == mMonth)
            {
                BuildCalendar(mCurrent.Value.AddMonths(1));
                return;
            }
            int newYear = mYear;
            int newMonth = mMonth + 1;
            int newDay = (mCurrent == null || mCurrent == NcCalendarDay.Empty) ? DateTime.Now.Day : mCurrent.Value.Day;

            int maxMonthOfYear = CultureInfo.CurrentCulture.Calendar.GetMonthsInYear(newYear);
            if (newMonth > maxMonthOfYear)
            {
                newYear++;
                DateTime maxDate = CultureInfo.CurrentCulture.Calendar.MaxSupportedDateTime.Date;
                if (newYear > maxDate.Year)
                    return;
                newMonth = 1;
            }

            int maxDayOfMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(newYear, newMonth);
            if (newDay > maxDayOfMonth) newDay = maxDayOfMonth;

            BuildCalendar(newYear, newMonth, newDay);
        }
        /// <summary>
        /// 向前一个月
        /// </summary>
        public void PreviousMonth()
        {
            if (mCurrent.Year == mYear && mCurrent.Month == mMonth)
            {
                BuildCalendar(mCurrent.Value.AddMonths(-1));
                return;
            }

            int newYear = mYear;
            int newMonth = mMonth - 1;
            int newDay = (mCurrent == null || mCurrent == NcCalendarDay.Empty) ? DateTime.Now.Day : mCurrent.Value.Day;

            DateTime minDate = CultureInfo.CurrentCulture.Calendar.MinSupportedDateTime.Date;
            if (newMonth < 1)
            {
                newYear = newYear - 1;
                if (newYear < minDate.Year) return;
                newMonth = CultureInfo.CurrentCulture.Calendar.GetMonthsInYear(newYear);
            }

            int maxDayOfMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(newYear, newMonth);
            if (newDay > maxDayOfMonth) newDay = maxDayOfMonth;

            BuildCalendar(newYear, newMonth, newDay);

        }
        /// <summary>
        /// 转到今天
        /// </summary>
        public void Today() { BuildCalendar(DateTime.Now.Date); }
        /// <summary>
        /// 设置“当前日”
        /// </summary>
        /// <param name="day"></param>
        /// <returns></returns>
        private bool setDay(int day)
        {
            foreach (NcCalendarWeek week in this)
            {
                foreach (NcCalendarDay one in week)
                {
                    if (!one.IsEmpty && one.Day == day)
                    {
                        if (mCurrent != null) mCurrent.IsCurrent = false;
                        mCurrent = one;
                        OnPropertyChanged(new PropertyChangedEventArgs("Current"));
                        OnPropertyChanged(new PropertyChangedEventArgs("Day"));
                        one.OnPropertyChanged("IsCurrent");
                        this.OnSelectedChanged(new EventArgs());
                        return true;
                    }
                    else
                    {
                        mCurrent = null;
                        this.OnPropertyChanged(new PropertyChangedEventArgs("IsCurrent"));
                    }
                }
            }
            return false;
        }

        private bool BuildCalendar(DateTime date) { if (date != null)  return BuildCalendar(date.Year, date.Month, date.Day); }
        /// <summary>
        /// 创建月历视图数据
        /// </summary>
        /// <param name="year"></param>
        /// <param name="month"></param>
        /// <param name="day"></param>
        /// <returns></returns>
        private bool BuildCalendar(int year, int month, int day)
        {
            if (mCurrent != null)
            {
                // 年、月、日均没有变化,不作任何改变
                if (year == mCurrent.Year && month == mCurrent.Month && day == mCurrent.Day) return true;
                // 年、月没有变化,不需要重建日期列表,定位当前日期
                if (year == mCurrent.Year && month == mCurrent.Month) return setDay(day);
            }

            DateTime minDate = CultureInfo.CurrentCulture.Calendar.MinSupportedDateTime.Date;
            DateTime maxDate = CultureInfo.CurrentCulture.Calendar.MaxSupportedDateTime.Date;
            int maxMonthOfYear = CultureInfo.CurrentCulture.Calendar.GetMonthsInYear(year);


            // 方案1:年月日不符合范围限定时,返回False
            if (year < minDate.Year || year > maxDate.Year || month < 1 || month > maxMonthOfYear) return false;

            // 方案2:年月日不符合范围限定时,规范到合理范围内
            //if (year < minDate.Year) year = minDate.Year;
            //if (year > maxDate.Year) year = maxDate.Year;
            //if (month < 1) month = 1;
            //if (month > maxMonthOfYear) month = maxMonthOfYear;


            DateTime firstDay = new DateTime(year, month, 1);
            int emptyDays = (int)firstDay.DayOfWeek;

            int days = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(year, month);
            int weeks = (int)Math.Ceiling(((float)days) / 7);

            if (day < 1 || day > days) day = (mCurrent != null) ? mCurrent.Day : 1;

            this.Clear();

            int dayOfWeekCount = 0;
            int weekCount = 0;
            NcCalendarWeek week = new NcCalendarWeek();
            NcCalendarDay item = NcCalendarDay.Empty;
            if (emptyDays > 0)
            {
                for (int i = emptyDays; i > 0; i--)
                {
                    item = new NcCalendarDay(firstDay.AddDays(-i));
                    item.Owner = this;
                    item.IsPreviousMonth = true;
                    week.Add(item);  //添加"上个月"的日期
                    dayOfWeekCount++;
                }
            }

            NcCalendarDay currentDayTo = null;
            for (int i = 1; i <= days; i++)
            {
                item = new NcCalendarDay(new DateTime(year, month, i));
                item.Owner = this;
                week.Add(item);
                dayOfWeekCount++;
                if (dayOfWeekCount >= 7)
                {
                    dayOfWeekCount = 0;
                    weekCount++;
                    this.Add(week);
                    week = new NcCalendarWeek();
                }
                if (i == day) currentDayTo = item;
            }


            firstDay = item.Value.Date;    // 借用firstDay变量
            if (dayOfWeekCount > 0)
            {
                for (int i = dayOfWeekCount; i < 7; i++)
                {
                    item = new NcCalendarDay(firstDay.AddDays(i - dayOfWeekCount + 1));
                    item.IsNextMonth = true;
                    item.Owner = this;
                    week.Add(item);  //添加"下个月"的日期
                }
                if (dayOfWeekCount < 7) this.Add(week);
            }

            //if (this.mCurrent == null || this.mCurrent != currentDayTo)
            if (this.mCurrent == null)
            {
                this.mCurrent = currentDayTo;
                this.OnSelectedChanged(new EventArgs());
            }

            mYear = year;
            mMonth = month;

            OnPropertyChanged(new PropertyChangedEventArgs("Day"));
            OnPropertyChanged(new PropertyChangedEventArgs("Month"));
            OnPropertyChanged(new PropertyChangedEventArgs("Year"));

            return true;
        }
        #endregion

        protected internal virtual void OnSelectedChanged(EventArgs e) { if (this.SelectedChanged != null) this.SelectedChanged(this, e); }
        protected internal virtual void OnCurrentChanged(EventArgs e) { if (this.CurrentChanged != null) this.CurrentChanged(this, e); }
    }
    public class NcCalendarWeek : ObservableCollection<NcCalendarDay>, INotifyPropertyChanged { }

WPF制作Calendar(3)

NcCalendarDay.cs:   

public class NcCalendarDay:INotifyPropertyChanged
    {
        public static readonly NcCalendarDay Empty = new NcCalendarDay();
        private DateTime mValue = new DateTime(1, 1, 1);
        private NcCalendar mOwner;
        private NcCalendarDay(){}
        private bool mIsPreviousMonth = false;
        private bool mIsNextMonth = false;

        public NcCalendarDay(DateTime oneDay)
        {
            mValue = oneDay;
        }

        public DateTime Value
        {
            get { return mValue; }
        }
        static NcCalendarDay()
        {
            CommandManager.RegisterClassCommandBinding(typeof(NcCalendarDay), new CommandBinding(Select, OnSelect));
        }

        #region Select
        /// <summary>
        /// 选择当前日期。
        /// </summary>
        public static RoutedUICommand Select { get { return mSelect; } }
        private static RoutedUICommand mSelect = new RoutedUICommand("Select", "Select", typeof(NcCalendarDay));

        private static void OnSelect(object sender, ExecutedRoutedEventArgs e)
        {
            Console.WriteLine("====");
            NcCalendarDay control = sender as NcCalendarDay;
            control.IsCurrent = true;
            if (control == null) return;
            // 命令实现代码
        }
        #endregion


        public int DayOfWeek { get { return (this.IsEmpty ? -1 : (int)mValue.DayOfWeek); } }

        public int Year { get { return (this.IsEmpty ? 0 : mValue.Year); } }

        public int Month { get { return (this.IsEmpty ? 0 : mValue.Month); } }

        public int Day { get { return (this.IsEmpty ? 0 : mValue.Day); } }

        public bool IsEmpty { get { return (this == NcCalendarDay.Empty); } }

        public bool IsToday { get { return mValue.Date == DateTime.Now.Date; } }

        public int WeekOfMonth
        {
            get
            {
                DateTime firstDay = new DateTime(mValue.Year, mValue.Month, 1);
                int emptyDays = (int)firstDay.DayOfWeek;
                return (int)Math.Ceiling((mValue.Day + emptyDays)/7f);
            }
        }

        public bool IsCurrent
        {
            get { return (mOwner != null && mOwner.Current == this); }
            set
            {
                if (mOwner == null) return;
                if (mOwner.Current == this) return;
                if (value)
                {
                    NcCalendarDay oldCurrent = mOwner.Current;
                    mOwner.Current = this;
                    OnPropertyChanged("IsCurrent");
                    if (oldCurrent != null) oldCurrent.OnPropertyChanged("IsCurrent");
                }
            }
        }

        public NcCalendar Owner
        {
            get { return mOwner; }
            internal set { this.mOwner = value; }
        }

        public bool IsPreviousMonth
        {
            get { return mIsPreviousMonth; }
            internal set { mIsPreviousMonth = value; }
        }
        public bool IsNextMonth
        {
            get { return mIsNextMonth; }
            internal set { mIsNextMonth = value; }
        }
        

        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 引发属性改变事件。
        /// </summary>
        /// <param name="propertyName">属性名称。</param>
        public void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventArgs args = new PropertyChangedEventArgs(propertyName);
            this.OnPropertyChanged(args);
        }
        /// <summary>
        /// 引发属性改变事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (this.PropertyChanged != null) this.PropertyChanged(this, e);
        }
        #endregion
    }

WPF制作Calendar(4)

<Style TargetType="{x:Type local:NcCalendarControl}">
        <Style.Resources>
            <Style TargetType="RepeatButton">
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="Foreground" Value="White"/>
                <Setter Property="Focusable" Value="False"/>
                <Setter Property="Control.Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="RepeatButton">
                            <Border Background="{TemplateBinding Background}" SnapsToDevicePixels="True" >
                                <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <DataTemplate x:Key="ncCalendarDayDateShowTemplate" DataType="{x:Type sysateTime}">
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
                    <TextBlock Foreground="White" Text="{Binding Path=Year}"/>
                    <TextBlock Foreground="White" Text="年"/>
                    <TextBlock Foreground="White" Text="{Binding Path=Month}"/>
                    <TextBlock Foreground="White" Text="月"/>
                    <TextBlock Foreground="White" Text="{Binding Path=Day}"/>
                    <TextBlock Foreground="White" Text="日"/>
                </StackPanel>
            </DataTemplate>

        </Style.Resources>
        <Setter Property="Width" Value="Auto"/>
        <Setter Property="Height" Value="Auto"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:NcCalendarControl}">
                    <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid Width="Auto" MinWidth="168" Height="Auto" MinHeight="100">
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition/>
                                <RowDefinition/>
                                <RowDefinition/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <Border Name="bdHeader" DataContext="{TemplateBinding Items}" Grid.Row="0" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                                <Grid Margin="3,3,3,3">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="0.5*"/>
                                        <ColumnDefinition Width="0.5*"/>
                                    </Grid.ColumnDefinitions>
                                    <StackPanel Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Left">
                                        <RepeatButton x:Name="btnPrvMonth" Content ="‹" Command="{x:Static local:NcCalendarControl.PreviousMonth}" BorderThickness ="0"/>
                                        <TextBlock FontFamily="Arial"  Margin="3,0,3,0"  Foreground="White" TextAlignment="Right" VerticalAlignment="Center" Text="{Binding Path=Month}" MinWidth ="16"/>
                                        <TextBlock FontFamily="Arial"  Margin="3,0,1,0"  Foreground="White" TextAlignment="Center" VerticalAlignment="Center" Text="月"/>
                                        <RepeatButton x:Name="btnNextMonth"  Content =" ›" Command="{x:Static local:NcCalendarControl.NextMonth}"/>
                                    </StackPanel>
                                    <StackPanel Orientation="Horizontal" Grid.Column="2" HorizontalAlignment="Right">
                                        <RepeatButton x:Name="btnPrvYear" Content ="‹‹" Command="{x:Static local:NcCalendarControl.PreviousYear}"/>
                                        <TextBlock FontFamily="Arial" Margin="5,0,5,0" Foreground="White" VerticalAlignment="Center" Text="{Binding Path=Year}"/>
                                        <RepeatButton x:Name="btnNextYear" Content ="››"  Command="{x:Static local:NcCalendarControl.NextYear}"/>
                                    </StackPanel>
                                </Grid>
                                <Border.Style>
                                    <Style TargetType="Border" x:Name="bdHeader">
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="1">
                                                <Setter Property="Background" Value="#FF73B5F7"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="2">
                                                <Setter Property="Background" Value="#FFCFF765"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="3">
                                                <Setter Property="Background" Value="#FF0FD60F"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="4">
                                                <Setter Property="Background" Value="#FFF7D64A"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="5">
                                                <Setter Property="Background" Value="#FF9C079C"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="6">
                                                <Setter Property="Background" Value="#FF53ADD6"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="7">
                                                <Setter Property="Background" Value="#FF5252BD"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="8">
                                                <Setter Property="Background" Value="#FFF00F0F"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="9">
                                                <Setter Property="Background" Value="#FFCDACE7"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="10">
                                                <Setter Property="Background" Value="#FFFFAE54"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="11">
                                                <Setter Property="Background" Value="#FFADA67C"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="12">
                                                <Setter Property="Background" Value="#FF05AC05"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="13">
                                                <Setter Property="Background" Value="#FFF0F0F0"></Setter>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </Border.Style>
                            </Border>
                            <Border Name="bdWeekTitle" DataContext="{TemplateBinding Items}" Grid.Row="1" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="1*"/>
                                        <ColumnDefinition Width="1*"/>
                                        <ColumnDefinition Width="1*"/>
                                        <ColumnDefinition Width="1*"/>
                                        <ColumnDefinition Width="1*"/>
                                        <ColumnDefinition Width="1*"/>
                                        <ColumnDefinition Width="1*"/>
                                    </Grid.ColumnDefinitions>
                                    <TextBlock Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Text="日" Grid.Column="0"/>
                                    <TextBlock Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Text="一" Grid.Column="1"/>
                                    <TextBlock Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Text="二" Grid.Column="2"/>
                                    <TextBlock Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Text="三" Grid.Column="3"/>
                                    <TextBlock Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Text="四" Grid.Column="4"/>
                                    <TextBlock Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Text="五" Grid.Column="5"/>
                                    <TextBlock Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Text="六" Grid.Column="6"/>
                                </Grid>
                                <Border.Style>
                                    <Style TargetType="Border" x:Name="bdWeekName">
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="1">
                                                <Setter Property="Background" Value="#FF509BEF"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="2">
                                                <Setter Property="Background" Value="#FFA5D610"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="3">
                                                <Setter Property="Background" Value="#FF05AC05"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="4">
                                                <Setter Property="Background" Value="#FFDEB511"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="5">
                                                <Setter Property="Background" Value="#FF6F076F"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="6">
                                                <Setter Property="Background" Value="#FF298CBD"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="7">
                                                <Setter Property="Background" Value="#FF383883"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="8">
                                                <Setter Property="Background" Value="#FFC51111"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="9">
                                                <Setter Property="Background" Value="#FFB58CDE"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="10">
                                                <Setter Property="Background" Value="#FFFF8402"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="11">
                                                <Setter Property="Background" Value="#FF9C9463"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="12">
                                                <Setter Property="Background" Value="#FF008500"></Setter>
                                            </DataTrigger>
                                            <DataTrigger Binding="{Binding Path=Month}" Value="13">
                                                <Setter Property="Background" Value="#FF0F0F0F"></Setter>
                                            </DataTrigger>
                                        </Style.Triggers>

                                    </Style>
                                </Border.Style>
                            </Border>
                            <Border Grid.Row="2" BorderThickness="1,1,0,0" BorderBrush="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
                                <ItemsControl Focusable="False" ItemsSource="{TemplateBinding Items}" ItemTemplate="{StaticResource ncCalendarWeekTemplate}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <StackPanel/>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                </ItemsControl>
                            </Border>
                            <Border Grid.Row="3" BorderThickness="0,0,1,1" BorderBrush="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
                                <Grid Background="SlateGray">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*" MinWidth="6"/>
                                        <ColumnDefinition Width="Auto"/>
                                    </Grid.ColumnDefinitions>
                                    <Button Margin="4,1,4,1" Grid.Column="0" Focusable="False" Content="今天" ToolTip="转到今天" Command="{x:Static local:NcCalendarControl.Today}" VerticalAlignment="Center" HorizontalAlignment="Center"></Button>
                                    <ContentPresenter Grid.Column="1" Content="{x:Static sysateTime.Now}" VerticalAlignment="Center" ContentTemplate="{StaticResource ncCalendarDayDateShowTemplate}"/>
                                    <ContentPresenter Grid.Column="3" Content="{TemplateBinding CurrentDay}" VerticalAlignment="Center" ContentTemplate="{StaticResource ncCalendarDayDateShowTemplate}"/>
                                </Grid>
                            </Border>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="Changeable" Value ="false">
                            <Setter TargetName="btnPrvYear" Property ="Visibility" Value ="Collapsed"/>
                            <Setter TargetName="btnPrvMonth" Property ="Visibility" Value ="Collapsed"/>
                            <Setter TargetName="btnNextYear" Property ="Visibility" Value ="Collapsed"/>
                            <Setter TargetName="btnNextMonth" Property ="Visibility" Value ="Collapsed"/>
                        </Trigger>
                        <Trigger Property="ShowHeader" Value ="false">
                            <Setter TargetName="bdHeader" Property ="Visibility" Value ="Collapsed"/>
                        </Trigger>
                        <Trigger Property="ShowWeekTitle" Value ="false">
                            <Setter TargetName="bdWeekTitle" Property ="Visibility" Value ="Collapsed"/>
                        </Trigger>
                        
                  
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

TOP

还在为头像烦恼?还在为不能关注好友动态烦忧?快来蓝色理想家园吧!

WPF制作Calendar(5)

<DataTemplate x:Key="ncCalendarDayTemplate" DataType="{x:Type local:NcCalendarDay}">
        <DataTemplate.Resources>
            <Style  TargetType="ToggleButton">
                <Setter Property="Background" Value="White"/>
                <Setter Property="MinHeight" Value="20"/>
                <Setter Property="MinWidth" Value="24"/>
                <Setter Property="Control.Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ToggleButton">
                            <Border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush ="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}">
                                <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataTemplate.Resources>
        <ToggleButton Name ="btnDay" BorderThickness="0,0,1,1" BorderBrush ="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" IsChecked="{Binding Path=IsCurrent,Mode=TwoWay}" Content="{Binding Path=Day}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" TextBlock.TextAlignment="Center"/>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=DayOfWeek}" Value="0">
                <Setter TargetName="btnDay" Property="Background" Value="Orange"/>
                <Setter TargetName="btnDay" Property="Foreground" Value="White"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=DayOfWeek}" Value="6">
                <Setter TargetName="btnDay" Property="Background" Value="SteelBlue"/>
                <Setter TargetName="btnDay" Property="Foreground" Value="White"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=IsNextMonth}" Value="True">
                <Setter TargetName="btnDay" Property="Foreground" Value="LightGray"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=IsPreviousMonth}" Value="True">
                <Setter TargetName="btnDay" Property="Foreground" Value="LightGray"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=IsToday}" Value="True">
                <Setter TargetName="btnDay" Property="Bac