Friday, April 4, 2008

Weird solutions: Ho can I force WPF control to rerender itself.

Today I found out some strange solution for forcing control to invalidate itself.

It turned out that by default control invalidates itself only in case it's render size has been changed, his visual parent has been changed, or some of it's dependency properties with AffectsRender option set is changed. (also there are some other weird cases when control suddenly decides to rerender it's appearance)

So I decided that maybe I can use FrameworkElement's ability to react to the AffectsRender option - I implemented the attached dependency property, and tried setting it to some rendom values on an object I needed to invalidate...and it worked :)

Here is some sample class, that could be used to implement such workaround:


public class RenderingHelper : DependencyObject
{
private static int s_last = 0;

public static int GetForceRerender( DependencyObject obj )
{
return (int)obj.GetValue( ForceRerenderProperty );
}
public static void SetForceRerender( DependencyObject obj, int value )
{
obj.SetValue( ForceRerenderProperty, value );
}

public static readonly DependencyProperty ForceRerenderProperty = DependencyProperty.RegisterAttached( "ForceRerender", typeof( int ), typeof( RenderingHelper ),
new FrameworkPropertyMetadata( 0, FrameworkPropertyMetadataOptions.AffectsRender ) );


public static void InvalidateRender( Visual target )
{
SetForceRerender( target, s_last++ );
}
}



You should keep in mind that invalidation of a visual calls it's OnRender method and recreates only part of the elements visual graph. All Visual's children are left the same, so if you need to invalidate the appearance of the entire visual subtree, you should add FrameworkPropertyMetadataOptions.Inherits to the property options.

1 comment:

ζ„šεƒδΈ€ said...

i have problem at: http://stackoverflow.com/questions/818911/force-a-wpf-control-to-refresh

i tried your class to fix it, but it doesn't work. do you have any ideas about my problem?