WPF Toolkit DatePicker Month/Year Only

前端 未结 7 521
暗喜
暗喜 2020-12-02 23:45

I\'m using the Toolkit\'s Datepicker as above but I\'d like to restrict it to month and year selections only, as in this situation the users don\'t know or care about the ex

7条回答
  •  余生分开走
    2020-12-03 00:15

    To add to Simon's brilliant answer, I've made some changes to DatePickerDateFormat.cs to prevent a bug where the Textbox momentarily flickers between dd/MM/yyyy (original string format) and MM/yyyy (overridden string format).

    This occurs due to the DatePicker setting the PART_Textbox text internally immediately before the dropdown is opened. It sets it to the string formatted text and there is ntohing you can do about it - it will override your binding.

    To prevent this behaviour, I added this code to the DatePickerDateFormat class from above.

    1. in ApplyDateFormat, get the dropdown button and handle PreviewMouseUp

      private static void ApplyDateFormat(DatePicker datePicker)
      {
          var binding = new Binding("SelectedDate")
                        {
                            RelativeSource = new RelativeSource { AncestorType = typeof(DatePicker) },
                            Converter = new DatePickerDateTimeConverter(),
                            ConverterParameter = new Tuple(datePicker, GetDateFormat(datePicker)),
                            StringFormat = GetDateFormat(datePicker) // This is also new but didnt seem to help
                        };
      
          var textBox = GetTemplateTextBox(datePicker);
          textBox.SetBinding(TextBox.TextProperty, binding);
      
          textBox.PreviewKeyDown -= TextBoxOnPreviewKeyDown;
          textBox.PreviewKeyDown += TextBoxOnPreviewKeyDown;
      
          var dropDownButton = GetTemplateButton(datePicker);
      
          datePicker.CalendarOpened -= DatePickerOnCalendarOpened;
          datePicker.CalendarOpened += DatePickerOnCalendarOpened;
      
          // Handle Dropdownbutton PreviewMouseUp to prevent issue of flickering textboxes
          dropDownButton.PreviewMouseUp -= DropDownButtonPreviewMouseUp;
          dropDownButton.PreviewMouseUp += DropDownButtonPreviewMouseUp;
      }
      
      private static ButtonBase GetTemplateButton(DatePicker datePicker)
      {
          return (ButtonBase)datePicker.Template.FindName("PART_Button", datePicker);
      }
      

    When PreviewMouseUp fires, if there is a Selected date, override the On Dropdown Shown behaviour (we mimic everything that the Datepicker does, but we don't set the PART_TextBox Text)

        /// 
        ///     Prevents a bug in the DatePicker, where clicking the Dropdown open button results in Text being set to default formatting regardless of StringFormat or binding overrides
        /// 
        private static void DropDownButtonPreviewMouseUp(object sender, MouseButtonEventArgs e)
        {
            var fe = sender as FrameworkElement;
            if (fe == null) return;
    
            var datePicker = fe.TryFindAncestorOrSelf();
            if (datePicker == null || datePicker.SelectedDate == null) return;            
    
            var dropDownButton = GetTemplateButton(datePicker);
    
            // Dropdown button was clicked
            if (e.OriginalSource == dropDownButton && datePicker.IsDropDownOpen == false)
            {                                
                // Open dropdown
                datePicker.SetCurrentValue(DatePicker.IsDropDownOpenProperty, true);
    
                // Mimic everything else in the standard DatePicker dropdown opening *except* setting textbox value 
                datePicker.SetCurrentValue(DatePicker.DisplayDateProperty, datePicker.SelectedDate.Value);
    
                // Important otherwise calendar does not work
                dropDownButton.ReleaseMouseCapture();
    
                // Prevent datePicker.cs from handling this event 
                e.Handled = true;                
            }
        }
    

    where the extension method TryFindAncestorOrSelf walks up the visual tree to find an object of type T. You can find an implementation of this here: http://www.hardcodet.net/2008/02/find-wpf-parent

    Hope this helps someone!

提交回复
热议问题