With Silverlight, Panels do not clip their contents by default. See the following example:
Where we have a Grid containing another Grid which itself contains an ellipse, and a Canvas which contains an ellipse:
Often this is not the desired effect (although it is actually quite a useful feature of Canvas; You can simply add a Canvas to your visual tree without explicitly or implicitly setting its Size and use it as a mechanism for absolute positioning its children).
Fortunately Silverlight provides a Clip property on UIElement, allowing you to provide the clipping geometry for the element:
The above example creates a clipping geometry which matches the rectangular geometry of the Grid itself. Clearly more funky clipping geometries can be created, allowing for really cool effects, however most of the time I simply want my Panel clipped so that its children cannot escape!
The above example has a few problems, Firstly, it is a bit long-winded having to explicitly create the geometry each time I want to clip; Secondly, if my Grid's size is calculated from its parent's layout, how can I define the clip geometry in my XAML?; Finally, if my Grid's geometry changes, its clipped geometry does not change.
In order to solve this problem I created a simple little attached behaviour, which allows you to define the clipping using the attached property Clip.ToBounds as illustrated below:
The result can be seen below:
And here is the code for the attached behaviour itself:
When the ToBounds property is associated with an element, ClipToBounds is invoked to create a rectangular clip geometry. We also add event handlers for Loaded, which is a very useful event which is fired when an element has been laid out and rendered, in other words it's size will have been computed, and SizeChanged. In the event handlers for both we simply update the clipping geometry.
This can be seen in action here, where clicking on the Grids or Canvas increases their size, with the clipping geometry growing accordingly: