从ViewModel阻止DatePicker更改

时间:2013-01-22 15:21:05

标签: c# wpf mvvm datepicker

我定义了一个简单的DatePicker:

<DatePicker SelectedDate="{Binding SomeDate}"/>

我想阻止用户在某些情况下清除该值。

这是我到目前为止所得到的:

public DateTime? SomeDate
{
    get { return someDate; }
    set
    {
        if (someDate != value)
        {
            if (value == null && someCondition)
                TellTheUserHeCannotClearTheField();
            else
                someDate = value;
            NotifyPropertyChanged(() => SomeDate);
        }
    }
}

虽然这样可以保持基础字段不被更新,但DatePicker仍然显示一个空值(即“&lt;在此输入文字&gt;”),并尝试每次再次将属性更新为null用户通过它进行选项卡。

如何强制DatePicker显示当前未更改的值?


根据Doc的评论回答,让我稍微概括一下。

使用下拉列表时,可以通过这种方式拒绝日期更改(例如,如果我想限制范围)。

但是如果你使用键盘,你输入的内容仍然存在,并且DatePicker会在每次失去焦点时尝试提交它。

3 个答案:

答案 0 :(得分:1)

我找到了一个相当不错的修复方法。

问题是SelectedDate属性已正确更新,但Text属性(显示的属性)现在不同步。

因此,我写了一个帮助器来保持同步:

public class SelectedDateSyncBehavior
{
    public static readonly DependencyProperty SyncTextProperty =
        DependencyProperty.RegisterAttached("SyncText", typeof(bool), 
            typeof(SelectedDateSyncBehavior), new PropertyMetadata(false, 
                                                  HandleSyncTextChanged));

    static void HandleSyncTextChanged(DependencyObject d, 
                                      DependencyPropertyChangedEventArgs e)
    {
        if ((bool)e.NewValue)
            ((DatePicker)d).LostFocus += SyncText;
        else
            ((DatePicker)d).LostFocus -= SyncText;
    }

    static void SyncText(object sender, RoutedEventArgs e)
    {
        var picker = (DatePicker)sender;
        if (picker.SelectedDate != null)
            picker.Text = picker.SelectedDate.Value.ToShortDateString();
    }

    public static void SetSyncText(DatePicker element, bool value)
    {
        element.SetValue(SyncTextProperty, value);
    }

    public static bool GetSyncText(DatePicker element)
    {
        return (bool)element.GetValue(SyncTextProperty);
    }
}

现在我所要做的就是:

<DatePicker SelectedDate="{Binding SomeDate}" 
            myns:SelectedDateSyncBehavior.SyncText="True"/>

答案 1 :(得分:0)

我似乎无法重现它。

我设置属性TestDate,如下所示:

private DateTime? _testDate = DateTime.Now;

public DateTime? TestDate {
  get { return _testDate; }
  set {
    if (value < DateTime.Now)
      System.Windows.MessageBox.Show("BAD!");
    else
      _testDate = value;
    OnPropertyChanged("TestDate");
  }
}

像这样的DatePicker:

<DatePicker SelectedDate="{Binding TestDate}" />

这是我的行为:

  • 选择“错误”日期(1月16日)

enter image description here

  • 错误消息

enter image description here

  • 价值与原始不变:

enter image description here

  • 选择好的约会(作品)

enter image description here

这个例子和你要做的一样,对吧? (我的MVVM实现有点不同。)

答案 2 :(得分:-1)

标准WPF DatePicker没有类似IsReadOnly的内容。阻止用户输入的唯一方法是禁用它:

<DatePicker SelectedDate="{Binding SomeDate}" IsEnabled="{Binding AllowEditSomeDate}"/>

视图模型:

public bool AllowEditSomeDate {get;set;} //Do not forget INotifyPropertyChanged