Raf
Raf

Reputation: 683

Calendar binding SelectedDate and DisplayDate: gray dates

The original use case:

This is a possible use case I'm trying to solve:

  1. The user opens the page with my calendar set to the now date
  2. User selects a date a few months back
  3. User refreshes the page, causing the selected date in the VM to be reset to the now date

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

Answers (2)

Mike T
Mike T

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

Raf
Raf

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

Related Questions