如何使边框修剪子元素?

时间:2011-04-13 13:15:11

标签: wpf

我的Border CornerRadius属性设置为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>

3 个答案:

答案 0 :(得分:20)

您可以为Clip属性编写转换器。例如,转换器应该实现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>

答案 1 :(得分:7)

通过使用OpacityMask属性,还可以解决您的问题仅限XAML。诀窍是在外边框内创建一个Grid并将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 Border也具有相同的CornerRadius

灵感来自:http://www.codeproject.com/Articles/225076/Creating-Inner-Shadows-for-WPF-and-Silverlight

答案 2 :(得分:1)

ClipToBounds是在这种情况下可能有用的属性。

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

这似乎暗示无法对边框进行简单剪裁。您可以将Clip属性设置为圆角矩形,但这不是很方便,因为我认为它的大小不能被限制。

您的选项似乎是使用OpacityMask和VisualBrush,或者通过使用MultiBinding&amp; amp;更新相关属性时重新创建剪辑。 MultiValueConverter ...