【问题标题】:How to style a control inside a border with a corner radius如何在具有圆角半径的边框内设置控件的样式
【发布时间】:2014-06-25 19:15:12
【问题描述】:

我有一个简单的窗口,其中包含一个带角半径的外边框和一个带背景的内边框。边框基本上只是我想放置在圆角外边框内的任何类型内容的占位符。

<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>

问题是内部控件没有继承圆角所以它在圆角之上绘制,像这样:

如何调整我的外部控件,使内部控件不会尝试在圆角上绘制。

在内部控件上设置圆角不是一个可行的选择,因为它会导致可怕的圆角半径重复。

【问题讨论】:

    标签: wpf


    【解决方案1】:

    我假设您在 Border 中有一个 Border 只是为了说明问题。如果可能,通过在外部 Border 中不包含任何控件来完全避免该问题,该控件会渲染角落中的任何内容。

    如果您必须包含一个在角落呈现某些内容的控件,您可以使用Clip

    <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>
    

    另一个选项(取决于您的具体情况)可能是将外部 Border 放置在其他内容的“上方”。只要将透明的FillIsHitTestVisible 设置为false,就足够了:

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

    【讨论】:

      【解决方案2】:

      RectangleGeometry 没有Width 属性,至少在 WPF 中是这样。

      为了我的需要,我必须创建一个IMultiValueConverter,如下所述:https://stackoverflow.com/a/5650367/2663813

      在那之后,我在拐角处仍然有问题,所以我使用了 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://stackoverflow.com/a/5650367/2663813">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();
          }
      

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-27
          • 1970-01-01
          相关资源
          最近更新 更多