日历绑定SelectedDate和DisplayDate:灰色日期

时间:2012-01-07 13:55:20

标签: c# .net wpf mvvm calendar

原始用例:

这是我试图解决的一个可能的用例:

  1. 用户打开页面,我的日历设置为现在的日期
  2. 用户选择几个月前的日期
  3. 用户刷新页面,导致VM中的所选日期重置为现在日期
  4. 预期:日历显示现在的日期

    实际:(仅对SelectedDate进行绑定)日历仅移动其选定日期,但会一直显示之前选择的月份

    我的解决方案:

    在MVVM场景中,我显示了一个Calendar控件,其SelectedDate与我的ViewModel中的SelectedDate属性绑定。我的VM中的属性在设置时触发它的PropertyChanged事件。

    我的VM中的所选日期也可以从我的代码中的其他部分设置,因此我希望我的日历始终显示所选日期(例如,当另一个月设置为所选日期时,我希望我的日历切换到那个月)。为了得到这种行为,我还将我的日历的DisplayDate属性绑定到我的SelectedDate属性,这给了我预期的行为,除非我点击上个月或下个月的灰色日期。

    这是我在XAML中的日历:

    <Calendar SelectedDate="{Binding Path=SelectedDate}" DisplayDate="{Binding Path=SelectedDate}" />
    

    这是我的ViewModel中的SelectedDate属性(实现INotifyPropertyChanged

        public DateTime SelectedDate
        {
            get 
            { 
                return selectedDate; 
            }
            set 
            { 
                selectedDate = value;
                this.PropertyChanged(this, new PropertyChangedEventArgs("SelectedDate"));
            }
        }
    

    解决方案的问题:

    显然点击灰色日期会导致鼠标按下SelectedDate,鼠标按下时再次设置,这会导致选择两个月后的日期。

    有没有更好的方法来实现这种行为?或者我可以修复DisplayDate问题(没有太多的黑客攻击,意味着代码背后没有/尽可能少的代码)?

    我真正想要的是SelecteDate属性,它也具有DisplayDate属性的行为:)

    感谢您的帮助!

2 个答案:

答案 0 :(得分:4)

我刚刚遇到这个问题并偶然发现了这个问题,虽然它有效但我进一步解构并发现解决方案非常简单。只需将DisplayDate绑定为Mode=OneTime即可。不需要任何其他东西。

DisplayDate="{Binding SelectedDate, Mode=OneTime, UpdateSourceTrigger=PropertyChanged}"
SelectedDate="{Binding SelectedDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

答案 1 :(得分:3)

我现在已经决定修复它的方式是在我的代码后面,在日历的加载事件上:

private void CalendarLoaded(object sender, RoutedEventArgs e)
{
    if (this.ViewStartCalendar.SelectedDate.HasValue)
    {
        this.ViewStartCalendar.DisplayDate = this.ViewStartCalendar.SelectedDate.Value;
    }
}

我宁愿在XAML或我的viewmodel中完成它,但我可以使用这个解决方案。