2011-03-27 61 views
5

我有一個簡單的窗口,包含一個帶有圓角半徑的外邊框和一個帶背景的內邊框。邊框基本上只是我想放置在圓角外邊框內的任何類型內容的佔位符。如何在一個帶有圓角的邊框內設計控件的樣式

<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

如何調整我的外部控制,所以內部控件不會嘗試在圓角的頂部繪圖。

在內部控制上設置圓角不是一個可行的選擇,因爲它會導致可怕的角部半徑重複。

回答

4

我假設你有一個BorderBorder只是爲了說明問題。如果可能的話,完全避免這個問題,因爲不包括外部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> 
0

一種可能性是把一些填充的外邊框:

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

,但是這可能會導致在應用程序中存在太多的空白區域。

1

RectangleGeometry沒有Width屬性,至少在WPF中。

我的需要,我不得不創建一個IMultiValueConverter如下所述:https://stackoverflow.com/a/5650367/2663813

在那之後,我仍然在角落的一個問題,所以我用肯特的第二個解決方案(注意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(); 
    }