DatePicker не обновляет модель представления, если фокус не изменяется на другой элемент управления - PullRequest
1 голос
/ 10 декабря 2011

Как я могу заставить элемент управления DatePicker обновлять модель представления без потери фокуса?

Я хотел бы иметь возможность запустить этот образец, введите 12/9/11 для даты, нажмите кнопку закрытиядля окна и иметь проход Debug.Assert.Если я открою текстовое поле перед закрытием окна, оно будет работать нормально.

<Window x:Class="DatePickerTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Closing="MainWindow_OnClosing">
    <StackPanel>
        <DatePicker Name="TheDate" SelectedDate="{Binding Path=SelectedDate}" />
        <TextBox/>
    </StackPanel>
</Window>
using System;
using System.ComponentModel;
using System.Diagnostics;

namespace DatePickerTest
{
   public partial class MainWindow
   {
      public MainWindow()
      {
         InitializeComponent();
         DataContext = new ViewModel();
      }

      private void MainWindow_OnClosing(object sender, CancelEventArgs e)
      {
         var dataContext = DataContext as ViewModel;
         Debug.Assert(dataContext.SelectedDate == new DateTime(2011, 12, 9));
      }
   }

   public class ViewModel
   {
      public DateTime SelectedDate { get; set; }
   }

}

Ответы [ 2 ]

11 голосов
/ 10 декабря 2011

Попробуйте изменить UpdateSourceTrigger на PropertyChanged, например,

<DatePicker Name="TheDate" 
            SelectedDate="{Binding Path=SelectedDate
                 , UpdateSourceTrigger=PropertyChanged
                 , Mode=TwoWay}" />

Обновление

Хорошо, похоже, это известная проблема с DatePicker. Вместо этого вы можете связать со свойством Text и установить TargetNullValue:

<DatePicker
   Name="TheDate"
   Text="{Binding Path=SelectedDate
          , Mode=TwoWay
          , UpdateSourceTrigger=PropertyChanged
          , ValidatesOnDataErrors=True
          , TargetNullValue=''}"
/>
2 голосов
/ 09 сентября 2017

Попробуйте это:

public class CustomDatePicker : DatePicker
{
    protected DatePickerTextBox _datePickerTextBox;

    public static readonly new DependencyProperty SelectedDateProperty =
        DependencyProperty.Register(nameof(SelectedDate), typeof(DateTime?), typeof(CustomDatePicker), 
            new FrameworkPropertyMetadata(null, SelectedDateChanged) { BindsTwoWayByDefault = true });

    private static new void SelectedDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((CustomDatePicker)d).SelectedDate = (DateTime?)e.NewValue;
    }

    public new DateTime? SelectedDate
    {
        get { return (DateTime?)GetValue(SelectedDateProperty); }
        set
        {
            if (base.SelectedDate != value) base.SelectedDate = value;
            if (this.SelectedDate != value) SetValue(SelectedDateProperty, value);
        }
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        _datePickerTextBox = this.Template.FindName("PART_TextBox", this) as DatePickerTextBox;
        if (_datePickerTextBox != null)
            _datePickerTextBox.TextChanged += dptb_TextChanged;
    }

    private void dptb_TextChanged(object sender, TextChangedEventArgs e)
    {
        int index = _datePickerTextBox.SelectionStart;
        string text = _datePickerTextBox.Text;

        DateTime dt;
        if (DateTime.TryParse(_datePickerTextBox.Text, Thread.CurrentThread.CurrentCulture,
            System.Globalization.DateTimeStyles.None, out dt))
            this.SelectedDate = dt;
        else
            this.SelectedDate = null;

        _datePickerTextBox.Text = text;
        _datePickerTextBox.SelectionStart = index;
    }
}

Это улучшенная версия того, что я нашел здесь . Он обновляет SelectedDate по мере ввода пользователем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...