除非焦点更改为另一个控件,否则DatePicker不会更新视图模型

时间:2011-12-09 21:14:07

标签: wpf datepicker

如何让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 个答案:

答案 0 :(得分:11)

尝试将UpdateSourceTrigger更改为PropertyChanged,例如

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

<强>更新

好吧,好像这是一个known issue DatePicker。您可以改为绑定到Text属性,并设置TargetNullValue

<DatePicker
   Name="TheDate"
   Text="{Binding Path=SelectedDate
          , Mode=TwoWay
          , UpdateSourceTrigger=PropertyChanged
          , ValidatesOnDataErrors=True
          , TargetNullValue=''}"
/>

答案 1 :(得分:2)

试试这个:

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;
    }
}

它是我发现here的改进版本。它会在用户输入时更新SelectedDate