2011-12-09 69 views
1

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

} 

回答

9

嘗試改變UpdateSourceTriggerPropertyChanged,例如

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

更新

好了,卻彷彿這是一個known issueDatePicker。您可以綁定到Text屬性來代替,並設置一個TargetNullValue

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

我更改了示例以使用您的建議,但它不起作用。我認爲UpdateSourceTrigger默認爲PropertyChanged,Mode默認爲TwoWay。 – Robin

+0

我已更新我的答案,並驗證它的工作原理。 – devdigital

+2

**評論來自[Robin](http://stackoverflow.com/users/108040/)(拒絕編輯):**這是有效的,謝謝。實際上,在這種情況下所需要的只是:' – Anne

1

試試這個:

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