Showing posts with label LinearGradientBrush. Show all posts
Showing posts with label LinearGradientBrush. Show all posts

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 – 


Tuesday, October 4, 2011

WPF Brushes


Brushes are used to fill area with color or graphics. Brushes can be used to fill background, foreground and border color of an element. Brush classes are available in System.Windows.Media namespace. In this post I will demonstrate frequently used brushes in WPF. Below are the list of most used brushes available in WPF.

List of brush classes
  • SolidColorBrush
  • LinearGradientBrush
  • RadialGradientBrush
  • ImageBrush
  • VisualBrush
  • BitmapCacheBrush

Let’s understand all the brushes with simple example.

<StackPanel>
<WrapPanel Margin="10">
<StackPanel>
    <Label Content="Solid Color Brush" Margin="5" />
    <Rectangle Height="100" Width="100" Margin="10">
        <Rectangle.Fill>
            <SolidColorBrush Color="Blue" />
        </Rectangle.Fill>
    </Rectangle>
</StackPanel>
<StackPanel>
    <Label Content="Linear Gradient Brush" Margin="5" />
    <Rectangle Height="100" Width="100" Margin="10">
        <Rectangle.Fill>
            <LinearGradientBrush >
                <GradientStop Color="Blue" Offset="0"/>
                <GradientStop Color="Cyan" Offset="0.4"/>
                <GradientStop Color="Red" Offset="1" />
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>
</StackPanel>
<StackPanel>
    <Label Content="Radia Gradient Brush" Margin="5" />
    <Rectangle Height="100" Width="100" Margin="10">
        <Rectangle.Fill>
            <RadialGradientBrush >
                <GradientStop Color="Blue" Offset="0"/>
                <GradientStop Color="Cyan" Offset="0.7" />
                <GradientStop Color="LightBlue" Offset="1" />
            </RadialGradientBrush>
        </Rectangle.Fill>
    </Rectangle>
</StackPanel>
</WrapPanel>
<WrapPanel Margin="10">
<StackPanel>
    <Label Content="Image Brush" Margin="5" />
    <Rectangle Height="100" Width="150" Margin="10">
        <Rectangle.Fill>
            <ImageBrush  ImageSource="Images\Desert.jpg"
                         Opacity="0.7" />
        </Rectangle.Fill>
    </Rectangle>
</StackPanel>
<StackPanel>
    <Label Content="Image Brush with TileMode" Margin="5" />
    <Rectangle Height="100" Width="200" Margin="10">
        <Rectangle.Fill>
            <ImageBrush ImageSource="Images\Play.ico"
                        TileMode="Tile" Stretch="Fill" 
                        Viewport="0,0,0.2,0.4" />
        </Rectangle.Fill>
    </Rectangle>
</StackPanel>
</WrapPanel>
<WrapPanel Margin="5">
<StackPanel>
    <Label Content="Image Brush with TileMode" Margin="2" />
    <TextBlock Height="100" Width="350" Margin="2"
                Text="WPF Brush" FontSize="65"
                FontFamily="Arial Rounded MT" >
        <TextBlock.Foreground>
            <ImageBrush  ImageSource="Images\Desert.jpg"
                         TileMode="Tile" Stretch="Fill"
                         Viewport="0,0,0.2,0.4" />
        </TextBlock.Foreground>
    </TextBlock>
</StackPanel>
</WrapPanel>
</StackPanel>



As shown in above image and code, First row displays use of Solid color brush, linear gradient brush and radial gradient brush. In second row Image Brush is used and in last image of second row imagebrush is used with tile mode. In third row Tilemode is applied to foreground color of Textblock.

VisualBrush

Visual brush allows visual representation of brush to fill an element’s surface. For example, using Visual brush we can copy the appearance of button inside rectangle. It just copy and fill the look of button into rectangle. Let’s have a look on below example.

<StackPanel>
<Button Content="VisualBrush"
        Name="visualBrushButton"
        Height="40" Width="150"
        Margin="10"/>
<Border BorderBrush="Blue"
        Height="150" Width="200"
        BorderThickness="2">
    <Rectangle Height="100" Width="150"
            Margin="10">
        <Rectangle.Fill>
            <VisualBrush
Visual="{Binding ElementName=visualBrushButton}"
                     Stretch="Fill" TileMode="Tile"/>
        </Rectangle.Fill>
    </Rectangle>
</Border>
</StackPanel>


As per above example, the stack panel contains button and rectangle. Rectangle is filled with Visual Brush and Visual brush’s visual element is bound with button. So rectangle will fill with button. You can see the button is filled inside rectangle.

BitmapCacheBrush

Bitmap cache brush is similar to visual brush but bitmap cache brush stores visual content in video memory of video card. So using bitmap cache, the content will redraw quickly when needed. Bitmap cache is more suitable in scenarios when user interface is loaded with heavy animation and complex vector content so in that scenario it will use content from cache memory. Bitmap cache brush has some significant memory impact because it takes little time to store content inside video memory. To use bitmap cache you need to set BitmapCatch property of BitmapCacheBrush. Let’s have a look on below code snippet.

<Rectangle Height="100"
           Width="150" Margin="10">
    <Rectangle.Fill>
        <BitmapCacheBrush
    Target="{Binding ElementName=visualBrushButton}"
    BitmapCache="BitmapCache" />
    </Rectangle.Fill>
</Rectangle>

BitmapCacheBrush is almost similar to VisualBrush so I have modified above example of VisualBrush with BitmapCacheBrush. BitmapCacheBrush has target property which contains the element and BitmapCache property. The output would be the same as per VisualBrush example. The difference here is BitmapCacheBrush will cache the element in video memory.

Hope you liked this article. Please feel free to write comments and feedback in comment section of this post.

See also –