Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make the contents of a round-cornered border be also round-cornered?

Tags:

wpf

I have a border element with rounded corners containing a 3x3 grid. The corners of the grid are sticking out of the border. How can I fix that? I tried using ClipToBounds but didn't get anywhere. Thanks for your help

like image 343
Gus Cavalcanti Avatar asked Nov 27 '08 20:11

Gus Cavalcanti


People also ask

Which property is used to make the border and rounded corners?

The border-radius property can be used to create rounded corners on elements.

How do you make a border with rounded corners in Word?

Click the Insert > Shapes button and choose the Rounded Rectangle tool. Draw a rectangle about the right size (not on top of the table, though).


2 Answers

Here are the highlights of this thread mentioned by Jobi

  • None of the decorators (i.e. Border) or layout panels (i.e. Stackpanel) come with this behavior out-of-the-box.
  • ClipToBounds is for layout. ClipToBounds does not prevent an element from drawing outside its bounds; it just prevents children's layouts from 'spilling'. Additionally ClipToBounds=True is not needed for most elements because their implementations dont allow their content's layout to spill anyway. The most notable exception is Canvas.
  • Finally Border considers the rounded corners to be drawings inside the bounds of its layout.

Here is an implementation of a class that inherits from Border and implements the proper functionality:

     /// <Remarks>     ///     As a side effect ClippingBorder will surpress any databinding or animation of      ///         its childs UIElement.Clip property until the child is removed from ClippingBorder     /// </Remarks>     public class ClippingBorder : Border {         protected override void OnRender(DrawingContext dc) {             OnApplyChildClip();                         base.OnRender(dc);         }          public override UIElement Child          {             get             {                 return base.Child;             }             set             {                 if (this.Child != value)                 {                     if(this.Child != null)                     {                         // Restore original clipping                         this.Child.SetValue(UIElement.ClipProperty, _oldClip);                     }                      if(value != null)                     {                         _oldClip = value.ReadLocalValue(UIElement.ClipProperty);                     }                     else                      {                         // If we dont set it to null we could leak a Geometry object                         _oldClip = null;                     }                      base.Child = value;                 }             }         }          protected virtual void OnApplyChildClip()         {             UIElement child = this.Child;             if(child != null)             {                 _clipRect.RadiusX = _clipRect.RadiusY = Math.Max(0.0, this.CornerRadius.TopLeft - (this.BorderThickness.Left * 0.5));                 _clipRect.Rect = new Rect(Child.RenderSize);                 child.Clip = _clipRect;             }         }          private RectangleGeometry _clipRect = new RectangleGeometry();         private object _oldClip;     } 
like image 128
Micah Avatar answered Oct 07 '22 06:10

Micah


Pure XAML:

<Border CornerRadius="30" Background="Green">     <Border.OpacityMask>         <VisualBrush>             <VisualBrush.Visual>                 <Border                      Background="Black"                     SnapsToDevicePixels="True"                     CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource AncestorType=Border}}"                     Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Border}}"                     Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType=Border}}"                     />             </VisualBrush.Visual>         </VisualBrush>     </Border.OpacityMask>     <TextBlock Text="asdas das d asd a sd a sda" /> </Border> 

Update: Found a better way to achieve the same result. You can also replace Border with any other element now.

<Grid>     <Grid.OpacityMask>         <VisualBrush Visual="{Binding ElementName=Border1}" />     </Grid.OpacityMask>     <Border x:Name="Border1" CornerRadius="30" Background="Green" />     <TextBlock Text="asdas das d asd a sd a sda" /> </Grid> 

Example

like image 23
Andrew Mikhailov Avatar answered Oct 07 '22 06:10

Andrew Mikhailov