UPDATES:
> You can see another simple example here.
> Why stop at simple geometry masks? Howabout images with holes?![]()
> Why stop at WPF? Here’s a Silverlight 3 version!
WPF’s Border element allows you to specify a different radius for each corner. Unfortunately it doesn’t clip content to fit inside the boundary (example here and below):
While there are other solutions, this one is my favorite so far:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="Black"> <!-- Rounded yellow border --> <Border BorderThickness="3" BorderBrush="Yellow" CornerRadius="10" Padding="2" HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid> <!-- Rounded mask (stretches to fill Grid) --> <Border Name="mask" Background="White" CornerRadius="7"/> <!-- Main content container --> <StackPanel> <!-- Use a VisualBrush of 'mask' as the opacity mask --> <StackPanel.OpacityMask> <VisualBrush Visual="{Binding ElementName=mask}"/> </StackPanel.OpacityMask> <!-- Any content --> <Image Source="http://chriscavanagh.files.wordpress.com/2006/12/chriss-blog-banner.jpg"/> <Rectangle Height="50" Fill="Red"/> <Rectangle Height="50" Fill="White"/> <Rectangle Height="50" Fill="Blue"/> </StackPanel> </Grid> </Border> </Page>
All it does is include a ‘mask’ Border element as a sibling of the content you want to clip. In the content it uses a VisualBrush bound to that mask. The mask will be automatically sized to your content, so it’s a nice "set and forget" solution
The downside is it won’t work in Silverlight because ElementName binding isn’t supported (yet). No doubt it’s possible to assign the VisualBrush in code-behind though! (let me know if you try it). (oops, neither is VisualBrush!). There’s now a Silverlight version here!
Hope this helps (and please let me know of any better / cleaner solutions).


69 comments
Comments feed for this article
October 4, 2008 at 8:40 am
Dew Drop - October 4, 2008 | Alvin Ashcraft's Morning Dew
[...] WPF – Easy Rounded Corners for Anything (Chris Cavanagh) [...]
October 28, 2008 at 8:49 pm
Daniel Kemper
Hi Chris,
Can you try something like this, at your leisure, with a file loaded as a resource, and let me know if you get strange results when resizing the window? The rounded corners seem to collapse. Here, I really just plugged in your XAML to the stock WPF project window.
October 28, 2008 at 8:51 pm
Daniel Kemper
… dont’ think the XAML pasted into the comment area made it to the published post. I’ll post a link to the full solution ….
Dan
October 28, 2008 at 8:53 pm
Daniel Kemper
Here you go!
http://dankemper.net/BorderMaskEx1.zip
Thanks,
Dan
October 28, 2008 at 10:22 pm
Chris Cavanagh
Daniel – The problem is caused by the image being stretched bigger than the available area. Because it’s contained in a StackPanel (with default vertical orientation) it’ll allow the content to grow as tall as it wants. To confirm this try changing the StackPanel to a Grid…
Are you wanting the brushed aluminum image to act as a background? If so, you might prefer to assign it as an ImageBrush to the StackPanel’s Background property (or do your own LinearGradientBrush with an aluminum OpacityMask…).
Hope this helps!
November 16, 2008 at 2:08 am
rem
Helpfull blog…
December 12, 2008 at 11:39 pm
Stewart Hyde
This is not exactly related to mask graphics issue here but I attempted to use this technique with WebBrowser control that is overlapping objects that are below the web control.
The web control is inside ScrollerViewe inside one of expanders. This is a set Grid and with bottom grid on top this so it at bottom of screen.
December 13, 2008 at 9:16 am
Chris Cavanagh
Stewart – I might be misunderstanding your comment, but WebBrowser isn’t a “proper” WPF control. It’s just a wrapper around the IE ActiveX control and suffers from several restrictions associated with ActiveX. The main problem is it can only render directly to the screen rather than arbitrary surfaces, so WPF can only control its size and position (and can’t do nice things like clip its corners or apply transformations).
Does that help?
December 13, 2008 at 9:20 am
Chris Cavanagh
Stewart – With some hacking, it is possible to get WPF to render and allow interaction with WebBrowser content, but it’s not pretty…
Take a look here: http://chriscavanagh.wordpress.com/2008/09/04/youcube/
December 29, 2008 at 10:59 am
James Foster
Why not just add a padding attribute to the outer border control? This seems overly complex. Am I missing something here???
December 29, 2008 at 11:20 am
Chris Cavanagh
James – The main goal of this is to allow any content to be clipped to a rounded border (or any shape actually), without having to know its size. While it’s easy to define a clip rectangle with rounded corners, you need to know the exact size… Padding only helps if your content doesn’t need to go right up against the border.
I’ve probably not explained it very well… Try the example above in Kaxaml or IE and resize the window. Then try doing the same thing using other methods. Definitely let me know if you find a simpler / better solution though; I certainly don’t claim to be an expert!
Thanks for the feedback!
February 9, 2009 at 4:25 am
Dean
Very nice tutorial!
March 16, 2009 at 5:35 pm
Sarkastik
One issue with this, I have an image with alpha transparency and don’t want the white background. Yet still need to have the image clipped.
March 16, 2009 at 8:56 pm
Chris Cavanagh
Sarkastik – Not sure if this will work for you, but you could try applying another opacity mask to the corner mask itself… Something like this:
http://www.chriscavanagh.com/chris/TransparencyClipTest/TransparentClipTest.xaml
April 3, 2009 at 2:41 am
David
Chris,
When I set this in a stackpanel as shown above I get no other content rendered inside the border.
April 3, 2009 at 2:55 am
David
Ref My post above, If I place the opacity mask on ANY placeholder then the rest of the content that it contains is not shown.
April 3, 2009 at 7:16 am
Chris Cavanagh
H David – Please send me some XAML that shows the problem. Some elements resize in interesting ways that can affect this (but I’ve not found any “impossible” cases… yet
)
April 6, 2009 at 12:55 am
David
…..rest of content
April 12, 2013 at 2:39 am
stoneweasel
I am having trouble with this leaving me with just the boarder visible with the entire contents of my grid / stack panel masked out. Any idea what I may be doing wrong for this to be happening?
April 12, 2013 at 7:46 am
Chris Cavanagh
stoneweasel – Can you email a code snippet to blog at chriscavanagh.com? Will take a look
April 6, 2009 at 12:57 am
David
Chris, Tried to post the Xaml here but it cuts out the markup. Can I email you the xaml I am using?
April 6, 2009 at 1:19 am
Chris Cavanagh
David – Just send to blog at chriscavanagh dot com
(or maybe the ‘send email’ option on my Contact page… I *think* it lets you paste code…)
April 6, 2009 at 6:52 am
David
Nope .. it says not to post code on the contact form
Will email @ above address
May 21, 2009 at 12:07 pm
David
Chris,
I’ve noticed that if you place any hardware accelerated effects onto items contained within the masked element that the masking breaks down. Don’t know if you’ve had this experience or know a work around but I thought it was worth mentioning.
May 21, 2009 at 12:18 pm
Chris Cavanagh
David – Can you send an example?
I tried a simple test here: http://www.chriscavanagh.com/chris/ClipWithShadow.xaml (you’ll need to download & run in Kaxaml/Xamlpad; you’ll probably get a UIPermission exception if you just open in IE).
May 26, 2009 at 3:41 am
David
Chris,
I figured it out, the item I was containing was a png image that had alot of transparency around the actual visible image. The overall image ran to the edge of the parent container with rounded corners. When the DropShadow is added the corners break. I placed a large margin around the image and the corners were sorted out.
May 26, 2009 at 6:48 am
Chris Cavanagh
David – Great! Could you send me a couple screenshots comparing the two? Thanks!
September 2, 2009 at 3:30 am
Anvaka
Hey Chirs. Thank you for sharing this. I wrote a simple wrapper around your solution, to make a free form borders. Check it out: http://stackoverflow.com/questions/1356999/wpf-freeform-border-control/1358132#1358132
September 2, 2009 at 6:43 am
Chris Cavanagh
Anvaka – That’s great!
I could use something like this for some of my apps. Thanks!
September 24, 2009 at 10:22 am
Mahesh
Thanks,
However, I am using expression blend for silverlight 3 and I am getting a message that “VisualBrush does not exist”
Am I missing something?
Please let me know.
Thanks again.
September 24, 2009 at 8:23 pm
Silverlight VisualBrush and rounded corners « Chris Cavanagh’s Blog
[...] · Leave a Comment As you know Silverlight 3 doesn’t support VisualBrush, which can make things like this pretty [...]
September 24, 2009 at 8:40 pm
Chris Cavanagh
Mahesh – Unfortunately Silverlight 3 doesn’t support VisualBrush so this method doesn’t work. Your comment prompted me to try a Silverlight version:
http://chriscavanagh.wordpress.com/2009/09/24/silverlight-visualbrush-and-rounded-corners/
Let me know if this helps!
November 21, 2009 at 8:45 am
PienaZupa
Any ideas how I could get a transparent background with this? Since the Border is used as an Opacity Mask, any tries to set transparency to it also sets transparency to the content.
Any ideas?
November 21, 2009 at 7:25 pm
Chris Cavanagh
PienaZipa – You should be able to do this with extra sibling elements to the mask; something like this:
http://www.chriscavanagh.com/chris/CornerClippingTransparency.xaml
(Try “download as” to get the xaml source). This example applies the OpacityMask to both siblings [of the mask], but you really only need to apply it to elements that need to be clipped (so for instance if a sibling had Margin=”20″ or something, it might not need clipping at all).
Hope tihs helps!
November 21, 2009 at 8:41 pm
PienaZupa
Thanks for replying. However, I tried your sample and, no matter how hard I try, it doesn’t work as desired (entirely transparent through to desktop – the window is semi-transparent).
I posted the relevant XAML for the ListBox at http://pastebin.com/m38a785c2 – could you please take a look at it? Thank you
November 21, 2009 at 10:41 pm
Chris Cavanagh
PienaZupa – I’ll take a look at this. Please describe exactly the effect/behavior you’re hoping to achieve
(can’t figure out from what you’ve sent so far).
November 22, 2009 at 6:45 am
PienaZupa
Thanks
Okay, first of all I have a window, which has the Aero-glass transparency effect – you can see the desktop. Then I have this semi-transparent listbox, for which I have created a custom style/controltemplate (it’s the code in the link I posted). This listbox, in turn, generates items which also have semi-transparent backgrounds.
In the end of the day a have a listbox with a bunch of items, but I can still see the desktop background through them (http://i48.tinypic.com/wa3td3.jpg),
However, if I use the mask as it is, I lose the transparency.
and I want to make the stackpanel or scrollviewer (the one that contains the generated items, it’s in the code I put in the pastebin) have rounded corners
Also for me setting an opacity for the listbox or scrollviewer or stackpanel isn’t going to work since it applies to children (including the generated text, as in the image)
January 21, 2010 at 11:07 am
Michael L. Long
Hello.
This seems a nice, quick way to get the job done. Definitely appreciate the info as we’re all encountering this problem when we really shouldn’t. WPF is all about a new presentation platform geared toward robust visuals (apart from the other important gui-seperation from code aspects) so for it NOT to provide a more streamlined, native approach at natural container clipping for complex custom borders is .. I’ll say annoying.
Anyway good stuff. I may have missed it but I didn’t see any addition by anyone to address linking the mask corner radius to the main form border radius so I added this to your solution in my code and it seems to work pretty well.
Assuming the name of the outer form border is borderMainWindow, the following lets the mask corner radius be flexible and not have to be touched again if you change the outer radius settings:
Thanks again for the good idea to get around this annoying issue.
-Michael
January 21, 2010 at 11:13 am
Michael L. Long
Guess I needed to wrap the XAML oops. I’ll try again. Probably be another missing chunk sorry if so.
Just in case wrapping in a code tag still didn’t work and my example doesn’t show up, all I’m doing is binding the CornerRadius of the mask to ElementName borderMainWindow, Path CornerRadius.
Sorry to clutter up the comments with failed attempts at posting my sample. Obliterate and rewrite as you see fit.
Thanks again,
-Michael
January 21, 2010 at 11:25 am
Chris Cavanagh
Michael – Thanks for the feedback (sorry for the lousy comment editor
). Good idea on binding the CornerRadius!
May 28, 2010 at 9:17 am
Kasper
Freakin Sweet! Thanks so much man. I have been looking for an easier way to accomplish this for some time. This is a great idea. Keep up the good work.
June 15, 2010 at 7:44 am
Easy rounded corners for anything | Mañé.NET
[...] http://chriscavanagh.wordpress.com/2008/10/03/wpf-easy-rounded-corners-for-anything/ wpf This entry was posted on Jun 15th, 2010 at 3:44 PM and is filed under Programming, [...]
June 23, 2010 at 8:07 am
Michaël
Hi Chris !
This is a nice tutorial, thank you. But I have a problem when I try to use this.
I apply the OpacityMask to a Canvas. The corner are rounded, that’s good but… my window is white ! The mask don’t act as an OpacityMask but as a brush.
However, I can always use my controls… if I find them ! :p
Do you have experienced this type of problem in the past ?
Regards,
Michaël
June 23, 2010 at 9:03 am
Chris Cavanagh
Michaël – It sounds like your mask is defined after the content you’re masking… This technique relies on your content “covering” the mask shape (ie being declared after it in the XAML). Or it could be another issue entirely
Could you mail me some sample XAML? (blog at chriscavanagh.com)
June 23, 2010 at 9:16 am
Michaël
Chris,
AS you ask me to do, I have send you a piece of code.
June 23, 2010 at 9:45 am
Chris Cavanagh
Michaël – Thanks for the example
The problem there is your mask is also the container of your content. The mask needs to be a “sibling” of your content (rather than a parent of it). Generally I find the best way is to use a Grid as the container/parent, then inside that have the mask (with no width or height specified so it fills the container) followed by the content. The content then has its OpacityMask pointing to the mask element (via the VisualBrush). Let me know if you need some more examples and I’ll fire you an email
(the blog comments section doesn’t like markup).
Hope this helps!
June 23, 2010 at 9:56 am
Michaël
Oh yes, I’m so studip. On all the example that I have seen, I don’t have noticed that the border is not containing the element I want to apply the mask.
I don’t know why, but I was SURE that the border contained the element on which I want to apply the mask. What a stupid mistake !
Thank you for your help Chris.
Regards,
Michaël
August 24, 2010 at 8:20 am
willie
If you replace the border with this
you will notice a small line and the left top between te yellow and the image which should not be there.
August 24, 2010 at 8:22 am
willie
(my code was gone, 2nd attempt)
If you replace the first border settings with
BorderThickness=”20″
CornerRadius=”60″
Padding=”0″
and the 2nd border mask with
CornerRaduis=”50″
You will notice a small black line at the left,top position between the yellow and the image
September 10, 2010 at 5:06 am
Eric
i f you need to create rounded image, you can try this
March 4, 2011 at 5:44 pm
Max Pavlov
The only problem is that you have to round to a certain background color, which creates only an illusion of rounded corners. You can’t place the rounded corners image on a non-white surface (in this particular example). If you do, you will end up with your image being rounded with white corners on some different background.
In my task I was to create an image from WPF object with rounded corners to place the image as an icon to notification area. This way I would get a dynamically generated notification area icon. This example doesn’t works in my particular case.
March 4, 2011 at 6:22 pm
Chris Cavanagh
Max – Can you send an example?
March 8, 2011 at 9:10 pm
Mike Kulls
Nice solution. It should be noted that in some cases you can just use the background of the border. This is true for your example of putting an image inside the border, you can just set the border’s background to an imagebrush.
I suspect this xaml will disappear but here is an example:
March 8, 2011 at 9:12 pm
Mike Kulls
Yep it did
Here is is without the gt and lts
Border BorderThickNess=5 CornerRadius=10
Border.BackGround
ImageBrush ImageSource=”path to image here”
Close Border.BackGround
Close Border
August 26, 2011 at 8:45 am
Bizunas
Note that WebBrowser is not native WPF control (because WebBrowser is made by using winforms host control), so it can’t be stylized like this.
August 26, 2011 at 9:20 am
Chris Cavanagh
Bizunas – That’s correct, although a WPF WebBrowser like this – http://chriscavanagh.wordpress.com/2009/08/25/a-real-wpf-webbrowser/ – should work fine
August 26, 2011 at 9:21 am
Chris Cavanagh
Note also that Awesomium now comes with its own .NET Wrapper; the styling ought to work well with that too
September 18, 2011 at 4:50 am
Saragani
Anyone has a solution/workaround for opacity mask not working correctly on 64 Bit machines (not always)?
For example:
If you put the XAML above in a Window, and compile your application as x64, then you will not see the text (or anything that is being masked).
It happens on Zoom and Rotate (a combination of them), for each scaling there are specific angles that the mask doesn’t render correctly.
Compiling my application as x86 is not an option.
I’ve tried other solutions for creating a round rectangle border like this, but Opacity Mask is the only one that gives the desired result, but still, other working solutions will be welcome.
Thanks
September 18, 2011 at 5:05 am
Saragani
mmm, the XAML I’ve posted is not visible…
Just have the XAML of this blog changed so the Grid will have RenderTransform with Render Group that contains RotateTransform of 45 deg, and then ScaleTransform of ScaleX and ScaleY equals to 2.
Bug already reported by my here:
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/25c05f8e-b8b8-4103-a5cf-2c51fc2d4b78
Sorry for the bad XAML on that example. That was after ripping all the XAMLs, DLLS, etc from the huge 40 Dlls project until I got a minimal project that simulates the problem (I only then discovered that the reason I couldn’t reproduce the problem on a clean solution was the fast that the new one was on x86… I didn’t know at that time that this problem is x64 related).
September 18, 2011 at 9:01 am
Chris Cavanagh
Saragani – That’s pretty strange. Is it possible to test in on non-NVidia machines? Seems they’ve had driver / WPF 64 issues in the past, so might be worth looking into:
http://connect.microsoft.com/VisualStudio/feedback/details/297127/broken-wpf-rendering-on-64bit-vista
October 15, 2011 at 3:05 am
pranav
How to clip window
October 15, 2011 at 8:29 am
Chris Cavanagh
pranav – See Cory Plotts’ comments here: http://social.msdn.microsoft.com/Forums/hu-HU/wpf/thread/91efcf9e-e887-405f-940d-0a57a697477c
December 7, 2011 at 1:14 pm
MM
The solution does not work if the horizontal- and verticalalignment is set to Strecth??
December 7, 2011 at 1:17 pm
Chris Cavanagh
MM – It should work with pretty much anything. Could you send an example? (email to blogmm@chriscavanagh.com).
December 19, 2011 at 2:44 pm
A WPF ListBox which acts like an Apple style navigation bar « marcelwouters
[...] We need a transparent border with rounded corners which clips the content. In the article WPF – Easy rounded corners for anything you can read how to achieve this. The result [...]
January 6, 2012 at 1:38 am
Ring
Hi,
First of all, thanks for this solution. Been cracking my head on how to get rid of the ugly corners of my contents within a rounded control.
But I’ve run into a weird (to me) issue when I tried to incorporate this into my project. I’m using a Selector, in which I have several “pages” which are essentially UserControls which I display one by one progressively. Something like a Wizard. All the pages utilizes your OpacityMask method to achieve the rounded corner effects. But somehow only the first page displayed is able to show the contents of the rounded control. In the subsequent pages, it’s almost like the the “mask” border is in front of the contents, or simply the contents are not displayed. I checked my codes numerous times, but cannot figure out why, coz all the codes are almost identical except for the contents.
I’m hoping you might have some ideas as to how this can happen and how to resolve this… Would be so grateful for your help…
January 6, 2012 at 6:17 am
Chris Cavanagh
Ring – Could you email me a sample that demonstrates the problem? (xaml at chriscavanagh dot com).
March 15, 2012 at 11:19 am
Wasiu
Works in my case, much simpler
March 15, 2012 at 11:21 am
Wasiu
–Border BorderBrush=”Black” Width=”60″ Height=”60″ CornerRadius=”7″–
–Border.Background–
–ImageBrush ImageSource=”{Binding Path=Photo}” Stretch=”Fill” /–
–/Border.Background–
–/Border–