如何为带有圆角的边框内的控件设置样式

7
我有一个简单的窗口,包含一个带圆角的外边框和一个带背景的内边框。这个边框基本上只是一个放置任何类型内容的占位符,我想把它放在圆角的外边框里面。
<Window x:Class="TestRunner.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" AllowsTransparency="True" 
        WindowStyle="None" Background="{x:Null}" >
    <Border BorderThickness="2" BorderBrush="Black" CornerRadius="8"  >     
           <Border Background="White">

           </Border>
    </Border>
</Window>

问题在于内部控件不会继承圆角,因此它们会在圆角上面绘制,如下所示: Bad corner rendering 我该如何调整外部控件,以使内部控件不试图在圆角上绘制?
将圆角设置在内部控件上不是可行的选择,因为这会导致可怕的圆角半径重复。
3个回答

5
我假设您在一个边框内部有另一个边框,这只是为了说明问题。如果可能的话,最好通过不在外部边框中包含任何控件来完全避免此问题,以便在角落里不呈现任何内容。
如果您必须包含在角落中呈现某些内容的控件,则可以使用剪辑。
<Border x:Name="border" CornerRadius="10">
    <Border.Clip>
        <RectangleGeometry Width="{Binding ActualWidth, ElementName=border}" Height="{Binding ActualHeight, ElementName=border}" RadiusX="10" RadiusY="10"/>
    </Border.Clip>

    <Border Background="White"/>
</Border>

根据您的具体情况,另一个选项可能是将外部边框放置在其他内容“上方”。只要它具有透明的填充并且IsHitTestVisible设置为false,就足够了:

<Grid>
    <Border Background="White"/>
    <Border CornerRadius="10" BorderBrush="Black" BorderThickness="3" Fill="Transparent" IsHitTestVisible="false"/>
</Grid>

2

RectangleGeometry在WPF中没有Width属性。

根据我的需求,我需要创建一个IMultiValueConverter,可以参考这里:https://dev59.com/CG035IYBdhLWcg3wC7qf#5650367

然而,在角落处仍然存在问题,所以我使用了Kent的第二种解决方案(请注意,Border.Fill也不存在)。

以下是我的代码:

<Grid>
    <Border x:Name="canvasBorder" CornerRadius="5">
        <Border.Resources>
            <tools:ContentClipConverter x:Key="ContentClipConverter" />
        </Border.Resources>
        <Border.Clip>
            <MultiBinding Converter="{StaticResource ContentClipConverter}">
                <Binding Path="ActualWidth"
                RelativeSource="{RelativeSource Self}"/>
                <Binding Path="ActualHeight"
                RelativeSource="{RelativeSource Self}"/>
                <Binding Path="CornerRadius"
                RelativeSource="{RelativeSource Self}"/>
            </MultiBinding>
        </Border.Clip>
        <!-- ... -->
    </Border>
    <Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Background="Transparent" IsHitTestVisible="false" />
</Grid>

在ContentClipConverter.cs文件中:

/// <summary>
/// Clips the content of a rounded corner border.
/// Code taken from <a href="https://dev59.com/CG035IYBdhLWcg3wC7qf#5650367">this topic</a>
/// </summary>
public class ContentClipConverter : IMultiValueConverter {
    /// <summary>
    /// Gets a clipping geometry for the item
    /// </summary>
    /// <param name="values">The input values</param>
    /// <param name="targetType">The parameter is not used.</param>
    /// <param name="parameter">The parameter is not used.</param>
    /// <param name="culture">The parameter is not used.</param>
    /// <returns>The clipping geometry</returns>
    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;
    }

    /// <summary>
    /// Not implemented
    /// </summary>
    /// <param name="value">The parameter is not used.</param>
    /// <param name="targetTypes">The parameter is not used.</param>
    /// <param name="parameter">The parameter is not used.</param>
    /// <param name="culture">The parameter is not used.</param>
    /// <returns>This function does not return anything</returns>
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
        throw new NotSupportedException();
    }

0

一种可能是在外边框上加一些填充:

<Border BorderThickness="2" BorderBrush="Black" CornerRadius="8" Padding="4">
    ....
</Border>

但这可能会导致您的应用程序中出现太多的空白。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接