2011-04-13 48 views
15

我有一个BorderCornerRadius属性设置为10.在那Border,有一个StackPanel。该面板分别包含两个带有蓝色和红色背景的Border如何使边界修剪子元素?

蓝色边框的左上角和右上角以及红色边框的左下角和右下角都伸出第一个边框的曲线边缘。我希望将蓝色和红色边框修剪到父边框。那可能吗?顺便说一下,我知道如果我为蓝色和红色边框的CornerRadius属性设置相同的值,它将遵循第一个曲线。我不想那样 - 我想修剪。谢谢!

<Border 
    Width="200" 
    Height="200" 
    BorderThickness="1" 
    BorderBrush="Black" 
    CornerRadius="10"> 
    <StackPanel> 
     <Border Height="100" Background="Blue" /> 
     <Border Height="100" Background="Red" /> 
    </StackPanel> 
</Border> 
+0

你能发表一些说明问题的代码吗? – 2011-04-13 13:19:06

回答

18

你可以写的剪辑属性的转换器。例如,转换器应实现IMultiValueConverter并绑定到实际大小和角半径。

public class BorderClipConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (values.Length == 3 && values[0] is double && values[1] is double && values[2] is CornerRadius) 
     { 
      var width = (double)values[0]; 
      var height = (double)values[1]; 

      if (width < Double.Epsilon || height < Double.Epsilon) 
      { 
       return Geometry.Empty; 
      } 

      var radius = (CornerRadius)values[2]; 

      // Actually we need more complex geometry, when CornerRadius has different values. 
      // But let me not to take this into account, and simplify example for a common value. 
      var clip = new RectangleGeometry(new Rect(0, 0, width, height), radius.TopLeft, radius.TopLeft); 
      clip.Freeze(); 

      return clip; 
     } 

     return DependencyProperty.UnsetValue; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 

用法:

<Border CornerRadius="10"> 
    <Border.Clip> 
     <MultiBinding Converter="{StaticResource BorderClipConverter}"> 
      <Binding Path="ActualWidth" 
         RelativeSource="{RelativeSource Self}"/> 
      <Binding Path="ActualHeight" 
         RelativeSource="{RelativeSource Self}"/> 
      <Binding Path="CornerRadius" 
         RelativeSource="{RelativeSource Self}"/> 
     </MultiBinding> 
    </Border.Clip> 
</Border> 
+0

我已经能够找到的最好的例子! – 2013-12-18 12:37:47

+0

我曾想过这样做,但想知道是否有一种XAML信条的方式。 我会试试这个。 我对此事的质疑: http:// stackoverflow。com/questions/24158147/wpf-clipping-a-border – 2014-06-11 09:34:02

+0

这可以用一个正常的转换器(即不是一个多值转换器)然后绑定到它自己来完成。这将使绑定更漂亮(即更容易重复使用),并推动把宽度/高度/半径抓进转换器的逻辑。 – claudekennilol 2016-06-03 16:06:12

1

ClipToBounds是可能有助于在这种情况下的财产。

编辑:经过一些测试,我注意到,ClipToBounds只关心实际的边界(即矩形区域的控制应用),所以还是内容在角落伸出...

这似乎暗示简单的裁剪到边界是不可能的。您可以将Clip属性设置为圆角矩形,但这并不是很方便,因为我认为它的大小不能被绑定。

您的选项似乎可以用一个OpacityMask连同VisualBrush或重建时的相关性通过使用MultiBinding & MultiValueConverter改变剪裁...

+0

我恐怕在这里无法使用Clip to Bounds。 – Boris 2011-04-13 13:44:03

+0

告诉我一些我不知道的... – 2011-04-13 13:44:55

+0

OpacticyMask只有几何类型,所以你仍然需要一些转换器,就像@MaratKhasanov的问题 – 2014-06-11 09:35:08

6

还有使用OpacityMask财产仅XAML的解决您的问题。诀窍是在外边框内创建一个Grid,并将网格的OpacityMask设置为充当剪贴蒙版的另一个元素。

<Border Width="200" Height="200" 
     BorderThickness="1" BorderBrush="Black" 
     CornerRadius="10"> 
    <Grid> 
     <Grid.OpacityMask> 
      <VisualBrush Visual="{Binding ElementName=clipMask}" Stretch="None" /> 
     </Grid.OpacityMask> 
     <Border x:Name="clipMask" Background="White" CornerRadius="10" /> 
     <StackPanel Background="White"> 
      <Border Height="100" Background="Blue" /> 
      <Border Height="100" Background="Red" /> 
     </StackPanel> 
    </Grid> 
</Border> 

在片段上方我用Border作为限幅掩模,但它也可以是另一种元素,只要它的填充颜色是不透明的。还要注意,clipMask边框也具有相同的CornerRadius

受启发︰http://www.codeproject.com/Articles/225076/Creating-Inner-Shadows-for-WPF-and-Silverlight