I'm doing custom rendering in a Decorator subclass. Our rendering requires creating complex geometries which only neded to be re-created when the actual rendered size changes. As such, I have moved the geometry creation into its own function called UpdateGeometry
which creates, then freezes the geometry for use in OnRender
. This new function only needs to be called in response to a change in ActualWidth
or ActualHeight
.
Even better, it looks like we should be able to simply override OnRenderSizeChanged
, which according to the documentation states...
"When overridden in a derived class, participates in rendering operations that are directed by the layout system. This method is invoked after layout update, and before rendering, if the element's RenderSize has changed as a result of layout update."
However, regardless if I'm using the override or listening to the property change notifications of ActualWidth
and ActualHeight
, my logging consistently shows OnRender
as happening first! Um... Wha??
To be sure it wasn't something I was doing in my code, I created a bare-bones test decorator subclass and added logging there, both on entry and exit to the overrides. Here is the entire class...
using System;
using System.Windows.Controls;
public class TestControl : Decorator
{
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
Console.WriteLine("OnRender Entered");
base.OnRender(drawingContext);
Console.WriteLine("OnRender Exited");
}
protected override void OnRenderSizeChanged(System.Windows.SizeChangedInfo sizeInfo)
{
Console.WriteLine("OnRenderSizeChanged Entered");
base.OnRenderSizeChanged(sizeInfo);
Console.WriteLine("OnRenderSizeChanged Exited");
}
}
And as I feared... here is the output...
OnRender Entered
OnRender Exited
OnRenderSizeChanged Entered
OnRenderSizeChanged Exited
So what am I missing here?
More importantly, how can I get the ActualWidth
and ActualHeight
values after the layout subsystem has done its job, but before the control is rendered so I can create the geometry before it's needed in the OnRender
override?
My latest implementation overrides ArrangeOverride
as the value that's passed in there is a size containing what the ActualWidth
and ActualHeight
values should be after the core layout system takes into consideration HorizontalAlignment
and VerticalAlignment
with values of 'Stretch', minimums and maximums, etc, but what they actually are depends on the value that's returned from that override so it's a little more complex than that.
Either way, I'm still wondering why the OnRenderSizeChanged
call doesn't happen when it's supposed to. Thoughts?
Mark