Critical Development

Language design, framework development, UI design, robotics and more.

Archive for November, 2010

Dynamic Clipping of Rounded Corners in Silverlight

Posted by Dan Vanderboom on November 6, 2010

I recently came across a nice article by Colin Eberhardt on automatically adjusting clipping bounds whenever the element to be clipped was resized, and I decided to make some small additions to make it work with rounded corners for a project I’m working on. Since Colin was generous enough to share his code, I’m going to share my additions as well.

Colin’s solution involves the creation of an attached property called Clip.ToBounds (a bool) applied to the item whose bounds you want to serve as a clipping path.  When this property is attached, it adds a listener to the Resize event and updates the clipping path when this happens.  Simple but effective.

I’ve added two more attached properties: Clip.RadiusX and Clip.RadiusY.

Here’s what the end result looks like:

image

The whole bordered area is a UserControl I created called ContentView.  Its root is a Border, which contains a Grid that is broken into three rows.  The top row contains a ContentHeader control, and the bottom row contains a ContentFooter control.  This is defined in the following code:

<UserControl
    x:Class="ClipRoundedCorners.ContentView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:ClipRoundedCorners"
    mc:Ignorable="d"
    d:DesignWidth="640" d:DesignHeight="480">

    <Border x:Name="LayoutRoot" BorderThickness="2" BorderBrush="White" CornerRadius="10">
        <Grid local:Clip.ToBounds="true" local:Clip.RadiusX="10" local:Clip.RadiusY="10">
            <Grid.RowDefinitions>
                <RowDefinition Height="84"/>
                <RowDefinition/>
                <RowDefinition Height="88"/>
            </Grid.RowDefinitions>
            <local:ContentHeader Margin="0"/>
            <local:ContentFooter Margin="0" d:LayoutOverrides="Width" Grid.Row="2"/>
            <ScrollViewer Margin="0" Grid.Row="1" Background="#FF545454"/>
        </Grid>
    </Border>
</UserControl>


The attached Clip properties are defined on the Grid control. Even though the Border defines its own CornerRadius, it’s the Grid within it that needs to set the clipping path.

Within the Clip class, I’ve updated the ClipToBounds method to set the RadiusX and RadiusY properties of the RectangleGeometry object used to set the clipping path.

private static void ClipToBounds(FrameworkElement Element)
{
    if (GetToBounds(Element))
    {
        Element.Clip = new RectangleGeometry()
        {
            Rect = new Rect(0, 0, Element.ActualWidth, Element.ActualHeight)
        };

        var rect = Element.Clip as RectangleGeometry;
        rect.RadiusX = GetRadiusX(Element);
        rect.RadiusY = GetRadiusY(Element);
    }
    else
    {
        Element.Clip = null;
    }
}

The complete Visual Studio 2010 (Silverlight 4) demo project can be downloaded here.

Resize your browser to see ContentView resize.  The clipping path updates like you’d expect it to.

Happy Silverlight coding!

Posted in Silverlight, User Interface Design | Tagged: , , , | 3 Comments »