views:

11

answers:

0

This is an interesting one. I've managed to get something working in WPF, but Silverlight is a different beast.

I have a relatively simple extension for Calendar called HolidayCalendar. Essentially there is a customized style containing elements for a custom background colour and caption based on the type of holiday. (National vs. state vs. personal) This extended calendar contains a list of holiday objects which are dates and type of holiday details. The elements in the calendarday control template use Converters to select colour and caption details.

The trouble is that when the user clicks on a calendar day, I capture the event (using a Attach on Left Mouse Button Down) and update the collection. But now I need to signal the calendar day (or calendar) to repaint itself.

In WPF, this could be accomplished by navigating the visual tree and resetting the element's binding. (basically setting the binding to exactly what it was.) This triggered the element to re-render. This trick does not appear to work in Silverlight, either by differences between the two environments, or the difference in binding. These converters use multi-bindings, which are available in WPF, but I'm using a Multi-Binding framework element and element-based binding in Silverlight. Clicking on another date triggers the previous date to re-paint and the converter updates the colour/caption as expected, so the converters and bindings are doing their jobs, but I need to trigger this repaint when a date is clicked.

XAML Style:

                       <this:MultiBinding x:Name="holidayColorBinding" Converter="{StaticResource colorConverter}"
                            NumberOfInputs="2"
                            Input1="{Binding}"
                            Input2="{Binding ElementName=uxCalendar}"/>
                    <Rectangle x:Name="HolidayBackground" IsHitTestVisible="False">
                        <Rectangle.Fill>
                            <Binding ElementName="holidayColorBinding" Path="Output"/>
                        </Rectangle.Fill>
                    </Rectangle>

Code to reset the binding: (triggered when a day is clicked.)

            var holidayBackgroundRect = VisualTreeHelper.GetChild(VisualTreeHelper.GetParent(e.OriginalSource as DependencyObject), 2) as Rectangle;
        holidayBackgroundRect.SetBinding(Rectangle.FillProperty, new Binding() { ElementName = "holidayColorBinding", Path = new PropertyPath("Output") });

I've removed the re-binding and the behaviour is the same, so the binding is not being updated. I think this may be because I want to refresh a binding from an element within the control template, but no idea how that might be done from code.

Here is the re-binding expression that works in WPF. This works because a multi-binding is a valid. XAML

                            <Rectangle x:Name="HolidayBackground" IsHitTestVisible="False" >
                            <Rectangle.Fill>
                                <MultiBinding Converter="{StaticResource colorConverter}">
                                    <Binding/>
                                    <Binding ElementName="uxCalendar" />
                                </MultiBinding>
                            </Rectangle.Fill>
                        </Rectangle>

Code to re-bind:

            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 = "uxCalendar" });
        binding.Converter = new CalendarDayColorConverter();
        holidayBackgroundRect.SetBinding(Rectangle.FillProperty, binding);

Any ideas?

Even if there is a way to signal the entire calendar to repaint I would be happy. (I've exhausted ideas there too.) (InvalidateMeasure, setting visibility=visible, nothing seems to do the trick.)

I really don't want to re-write a calendar control that actually supports binding to a proper list of dates. (Though I might be tempted as a side project because the WPF/Silverlight calendars are pretty hacky.)