【问题标题】:DatePicker doesn't update view model unless focus changes to another control除非焦点更改为另一个控件,否则 DatePicker 不会更新视图模型
【发布时间】:2011-12-09 21:14:07
【问题描述】:

如何让 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; }
   }

}

【问题讨论】:

标签: wpf datepicker


【解决方案1】:

尝试将UpdateSourceTrigger 更改为PropertyChanged,例如

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

更新

好的,这似乎是带有DatePickerknown issue。您可以改为绑定到Text 属性,并设置TargetNullValue

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

【讨论】:

  • 我更改了示例以使用您的建议,但它不起作用。我认为 UpdateSourceTrigger 默认为 PropertyChanged,Mode 默认为 TwoWay。
  • Robin 的评论(被拒绝编辑): 行得通,谢谢。实际上,在这种情况下只需要:&lt;DatePicker Name="TheDate" Text="{Binding Path=SelectedDate, Mode=TwoWay}" /&gt;
  • 绑定到文本会导致某些日期格式,例如 dd.mm.yyyy。无法正确解析
【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-21
    相关资源
    最近更新 更多