Tuesday, December 27, 2011

Freezable Objects in WPF



Freezable is a type which represents frozen and unfrozen states. When object state is frozen, no one can modify the object. Freezable class provides Freeze method to freeze object. Once object is frozen, can never be reverted to unfrozen state. Freezable class provides clone method to clone frozen object to another unfrozen object.

Not necessary that every Freezable objects can be frozen so before calling freeze method need to check whether object can be freezable or not using CanFreeze property. Forcefully freeze an unfreezable object throws InvalidOperationException.  CanFreeze returns true if object is freezable else return false. IsFrozen property returns true if an object is already freeze otherwise returns false. It is best practice to freeze an object (if freezable) which is not going to modify until application ends.

Why Freeze an object?

There are classes like Brush, Camera, Transform, Geometry, BitmapEffect are derived from Freezable class. Some of these graphic related objects contain unmanaged resources so when change in original object, system must monitor these object modification and need to update corresponding unmanaged resources as well. These might cause performance hit because system needs to monitor resource even there is no change in original object. Freezable class can help to improve WPF application performance.

Let’s have a look on below code.

XAML

<Grid>
    <Label Content="Hello"
            Name="MyText"
            HorizontalContentAlignment="Center"
            FontSize="30"
            Width="200" Height="50" />
</Grid>

Code

void FreezableObjects_Loaded(object sender, RoutedEventArgs e)
{
    RadialGradientBrush radialBrush = new RadialGradientBrush();
    radialBrush.GradientStops.Add(new GradientStop(Colors.Red, 0.2));
    radialBrush.GradientStops.Add(new GradientStop(Colors.White, 0.9));

    MyText.Background = radialBrush;

    if (radialBrush.CanFreeze)
        radialBrush.Freeze();

    if (radialBrush.IsFrozen)
    {
        radialBrush.GradientStops.Add(
             new GradientStop(Colors.Blue, 0.4)); //Throws InvalidOperationException. Can’t modify frozen object.

    }
}



How to clone frozen objects?

void FreezableObjects_Loaded(object sender, RoutedEventArgs e)
{
    RadialGradientBrush radialBrush = new RadialGradientBrush();
    RadialGradientBrush radialBrushClone = new RadialGradientBrush();
    
    radialBrush.GradientStops.Add(new GradientStop(Colors.Red, 0.2));
    radialBrush.GradientStops.Add(new GradientStop(Colors.White, 0.9));
    
    MyText.Background = radialBrush;

    if (radialBrush.CanFreeze)
        radialBrush.Freeze();

    if (radialBrush.IsFrozen)
    {
        radialBrushClone = radialBrush.Clone();
        radialBrushClone.GradientStops.Add(new GradientStop(Colors.Blue, 1));
        MyText.Background = radialBrushClone;
    }
}


As per first example, once radialBrush object is frozen and tries to modify the radiaBrush object throws an InvalidOperationException. Another example demonstrate how to create clone object from frozen object.

See Also – 


No comments:

Post a Comment