I have an extended Calendar control that is bound to a class containing a date and state values. The idea is essentially differentiate between national holidays, state holidays, and personal days off. I render these in different colours using a Converter that inspects the current date against the list of objects associated with the calendar control to choose a fill colour for an element in the CalendarDay. This all works perfectly.
The issue is that I want to support that when the user clicks on a day (in a given mode) they can select, or de-select that date as a day off/holiday. using the PreviewMouseDown I select the object by the selected data context (datetime) and update it's state. This works fine, however I cannot get the calendar control to performa a refresh.
The calendar is not bound to my custom class, I'm not sure exactly how a CalendarDay is bound, but it appears to just have a data context pointing at a DateTime value. So NotifyPropertyChanged is out. If I click on a date and switch months and back the date appe开发者_C百科ars highlighted as expected, what I need is to tell the calendar to repaint. I've been scouring for examples on forcing repaints, and nothing has worked so far.
I've tried UpdateLayout() amongst other things. I don't know if this is an issue because I'm trying to re-render from within a mouse event. Any ideas how to repaint a calendar control so that a converter can be kicked off?
FINALLY found it. Posting for prosperity in case others have been trying to do something similar.
As mentioned in the comment, setting the fill colour of the element did change the background colour, but did so for that day in all months. This made sense actually because the fill was normally managed by the template and set based on binding and a converter.
The solution was to reset the binding on the mouse down event when a date is clicked. This is the event code:
protected override void OnPreviewMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
if (!(e.OriginalSource is FrameworkElement &&
(e.OriginalSource as FrameworkElement).DataContext is DateTime))
{
base.OnPreviewMouseLeftButtonDown(e);
return;
}
DateTime dateTime = (DateTime)(e.OriginalSource as FrameworkElement).DataContext;
var calendarDay = _calendarDays.Single(d => d.CalendarDate == dateTime);
if (calendarDay.IsHoliday)
{
calendarDay.CalendarKey = null;
}
else
{
calendarDay.CalendarKey = Guid.NewGuid();
}
var holidayBackgroundRect = VisualTreeHelper.GetChild(VisualTreeHelper.GetParent(e.OriginalSource as DependencyObject), 1) as Rectangle;
var binding = new MultiBinding();
binding.Bindings.Add(new Binding());
binding.Bindings.Add(new Binding() { ElementName = "Calendar" });
binding.Converter = new CalendarDayColorConverter();
holidayBackgroundRect.SetBinding(Rectangle.FillProperty, binding);
base.OnPreviewMouseLeftButtonDown(e);
}
The converter is what determines the day's colour. it accepts the current bound date from the calendar, and the calendar control itself where it can retrieve the current list of holidayDays.
By re-specifying the binding, it forces the calendar day to refresh that date.
What a complete pain that has been.
精彩评论