Reputation: 683
The original use case:
This is a possible use case I'm trying to solve:
Expected: The calendar displays the now date
Actual: (with binding only on SelectedDate) The calendar only moves its selected date, but keeps showing the previously selected month
My solution:
In an MVVM scenario I am showing a Calendar
control whose SelectedDate has a binding to a SelectedDate
property in my ViewModel. The property in my VM triggers it's PropertyChanged
event when set.
The selected date in my VM can also be set from other parts in my code, so I want my calendar to always show the selected date (for example when another month is set as the selected date, I want my calendar to switch to that month). To get this behavior I also bound the DisplayDate
property of my calendar to my SelectedDate property, and this gives me the expected behavior, except when I click on the gray dates of the previous or next month.
This is my Calendar in XAML:
<Calendar SelectedDate="{Binding Path=SelectedDate}" DisplayDate="{Binding Path=SelectedDate}" />
This the SelectedDate
property in my ViewModel (implements INotifyPropertyChanged
)
public DateTime SelectedDate
{
get
{
return selectedDate;
}
set
{
selectedDate = value;
this.PropertyChanged(this, new PropertyChangedEventArgs("SelectedDate"));
}
}
The problem with the solution:
Apparently clicking on a gray date causes the SelectedDate
to be set on mouse down and again on mouse up, which causes a selection of a date two months away.
Is there a better way to implement this kind of behavior? Or can I fix the DisplayDate problem (without too much hacking, meaning no/as little code as possible in code behind)?
All I really want is a SelecteDate
property which also has the behavior of the DisplayDate
property :)
Thank you for your help!
Upvotes: 3
Views: 7690
Reputation: 59
I've just had this problem arise and stumbled upon this answer which although it worked I deconstructing further and found the solution is extremely simple. Simply bind to the DisplayDate
as Mode=OneTime
. Nothing else is needed.
DisplayDate="{Binding SelectedDate, Mode=OneTime, UpdateSourceTrigger=PropertyChanged}"
SelectedDate="{Binding SelectedDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Upvotes: 5
Reputation: 683
The way I have settled on fixing it now is in my code behind, on the loaded event of the calendar:
private void CalendarLoaded(object sender, RoutedEventArgs e)
{
if (this.ViewStartCalendar.SelectedDate.HasValue)
{
this.ViewStartCalendar.DisplayDate = this.ViewStartCalendar.SelectedDate.Value;
}
}
I would have rather done it in XAML or in my viewmodel, but I can live with this solution.
Upvotes: 3