
在上一篇文章中,出现了一个BUG,设置DatePicer控件输入只读,并非是真真的只读,仍可以进行删除,这与只读的概念相违背了,利用TextBox的IsReadonly属性可以实现这一要求,不需要自己去定义只读!
二、新的需求在很多需求中,只需要选择年,或者是只需要选择月。在界面中,很多程序往往只使用ComboBox来实现这一需求。但是DatePicker完全能够实现,大家都知道DatePicer控件使用了一个隐藏的 Calendar控件!手动更改CalendarMode属性完全可以实现!因此,在DatePicker控件中,添加属性DateMode属性,继承自CalendarMode,通过改变DateMode属性来实现效果!
同时,要用到扩展方法(在本例中方法名:public static IEnumerable<DependencyObject> Descendents(this DependencyObject root)){})!它是一个静态类中的一个静态方法,通过此方法在DependencyObject类型中添加Descendents。在本例中的目的是为了找到Calendar控件!具体如何使用,请查找相关的资料了!
二、代码 public static class ControlsHelper { /// <summary> /// 扩展DependencyObject Descendents方法,递归找到制定的控件 /// </summary> /// <param name="root"></param> /// <returns></returns> public static IEnumerable<DependencyObject> Descendents(this DependencyObject root) { int count = VisualTreeHelper.GetChildrenCount(root); for (int i = 0; i < count; i++) { var child = VisualTreeHelper.GetChild(root,i); yIEld return child; foreach (var descendent in Descendents(child)) yIEld return descendent; } } } public class DatePickerEx : DatePicker { #region 私有字段 DatePickerTextBox CurrentTextBox;//DatePicker的文本框控件 Popup CurrentPopup;//DatePicker控件的TempPart Calendar CurrentCalendar;//日历控件 button CurrentButon;//DatePicker的button控件 string DateFormat;//定义时间显示格式 string _inputText; public static Readonly DependencyProperty IsReadonlyProperty = DependencyProperty.Register("IsReadonly",typeof(bool),typeof(DatePickerEx),new PropertyMetadata(false)); //public static Readonly DependencyProperty inputTextProperty = DependencyProperty.Register("inputText",typeof(String),new PropertyMetadata("",inputTextChanged)); public static Readonly DependencyProperty DateModeProperty = DependencyProperty.Register("DateMode",typeof(CalendarMode),new PropertyMetadata(CalendarMode.Month,DateModeChanged)); #endregion #region 属性 /// <summary> /// 得到手动输入的值 /// </summary> public string inputText { //get { return (string)GetValue(inputTextProperty); } //set { SetValue(inputTextProperty,value); } get { return _inputText == null ? "" : _inputText; } private set { _inputText = value; } } /// <summary> /// 启用和关闭手动输入 /// </summary> public bool IsReadonly { get { return (bool)GetValue(IsReadonlyProperty); } set { SetValue(IsReadonlyProperty,value); } } ///// <summary> /// 输入时间类型 /// </summary> public CalendarMode DateMode { get { return (CalendarMode)GetValue(DateModeProperty); } set { SetValue(DateModeProperty,value); } } #endregion #region 重写方法及事件 public overrIDe voID OnApplyTemplate() { base.OnApplyTemplate(); this.CurrentTextBox = GetTemplateChild("TextBox") as DatePickerTextBox; this.CurrentPopup = GetTemplateChild("Popup") as Popup; this.CurrentButon = GetTemplateChild("button") as button; #region 注册及绑定事件 if (null != this.CurrentTextBox) { //this.CurrentTextBox.borderThickness = new Thickness(1); //this.CurrentButon.margin = new Thickness(-25,0); this.SetTextMode(this.CurrentTextBox); this.CurrentTextBox.IsReadonly = this.IsReadonly; this.CurrentTextBox.TextChanged += ((sender,e) => { if (this.IsReadonly) this.CurrentTextBox.Text = this.SelectedDate.HasValue ? this.SelectedDate.Value.ToString(this.DateFormat) : ""; else { if (this.CurrentTextBox.Text.Trim().Length >= this.DateFormat.Length) { DateTime timeTemp; if (DateTime.TryParse(this.CurrentTextBox.Text.Trim(),out timeTemp)) this.CurrentTextBox.Text = timeTemp.ToString(this.DateFormat); } this.inputText = this.CurrentTextBox.Text; } SetTextMode(this.CurrentTextBox); }); } this.CalendarClosed += new RoutedEventHandler(DatePickerEx_CalendarClosed); if (this.DateMode == CalendarMode.Month) return; if (null != this.CurrentPopup) //利用扩展方法找到Calendar控件 this.CurrentCalendar = this.CurrentPopup.Child.Descendents().OfType<Calendar>().FirstOrDefault(); if (null != this.CurrentButon) this.CurrentButon.Click += ((sender,e) => { this.CurrentPopup.IsOpen = true; }); if (null != this.CurrentCalendar) { this.CurrentCalendar.IsTodayHighlighted = true; this.CurrentCalendar.displayModeChanged += new EventHandler<CalendarModeChangedEventArgs>(CurrentCalendar_displayModeChanged); this.CurrentCalendar.displayMode = this.DateMode; this.CurrentCalendar.LostMouseCapture += ((sender,e) => { this.SelectedDate = this.displayDate; }); } #endregion } voID CurrentCalendar_displayModeChanged(object sender,CalendarModeChangedEventArgs e) { this.CurrentCalendar.displayModeChanged -= CurrentCalendar_displayModeChanged; this.CurrentCalendar.displayModeChanged += CurrentCalendar_displayModeChanged; Calendar cal = (Calendar)sender; //首次加载以及重新赋值displayMode Calendar视图情况判断 if (e.oldMode.Equals(CalendarMode.Year) && !e.NewMode.Equals(CalendarMode.Month)) cal.displayMode = e.NewMode; else cal.displayMode = this.DateMode; //仅选择月 Calendar关闭情况判断 if (e.NewMode.Equals(CalendarMode.Month)) this.CurrentPopup.IsOpen = false; //只选择年。 Calendar 关闭情况判断 if (this.DateMode == CalendarMode.Decade && e.NewMode == CalendarMode.Year && e.oldMode == this.DateMode) this.CurrentPopup.IsOpen = false; } /// <summary> /// 设置日期显示格式 /// </summary> /// <param name="tbx"></param> protected voID SetTextMode(DatePickerTextBox tbx) { if (null == tbx) return; switch (this.DateMode) { case CalendarMode.Year: DateFormat = "yyyy-MM"; tbx.Watermark = "<yyyy-MM>"; break; case CalendarMode.Decade: DateFormat = "yyyy"; tbx.Watermark = "<yyyy>"; break; default: DateFormat = "yyyy-MM-dd"; break; } tbx.UpdateLayout(); } #endregion //protected overrIDe #region 自定义事件 protected overrIDe voID OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); if (!this.IsReadonly) this.inputText = this.CurrentTextBox.Text; } protected virtual voID DatePickerEx_CalendarClosed(object sender,RoutedEventArgs e) { if (null != this.SelectedDate) this.Text = this.SelectedDate.Value.ToString(this.DateFormat); this.inputText = this.Text; } //protected static voID inputTextChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) //{ // DatePickerEx sender = d as DatePickerEx; // if (null != sender.CurrentTextBox) // sender.CurrentTextBox.Text = e.NewValue.ToString(); //} protected static voID DateModeChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) { DatePickerEx sender = d as DatePickerEx; if (null != sender.CurrentCalendar) sender.CurrentCalendar.displayMode = (CalendarMode)e.NewValue; sender.SetTextMode(sender.CurrentTextBox); } #endregion } 总结 以上是内存溢出为你收集整理的Silverlight 学习——重写DatePicker (二)全部内容,希望文章能够帮你解决Silverlight 学习——重写DatePicker (二)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)