2014-06-11 81 views
5

我需要創建一個圓形的PrograssBar模板。WPF剪裁邊框

控件模板:

<ControlTemplate TargetType="{x:Type ProgressBar}"> 
    <Grid x:Name="TemplateRoot" SnapsToDevicePixels="true">      
    <Rectangle x:Name="PART_Track" Margin="1" Fill="White" /> 

    <Border x:Name="PART_Indicator" HorizontalAlignment="Left" Margin="1" > 
     <Grid x:Name="Foreground" > 
      <Rectangle x:Name="Indicator" Fill="{TemplateBinding Background}" /> 
      <Grid x:Name="Animation" ClipToBounds="true" > 
       <Rectangle x:Name="PART_GlowRect" Fill="#FF86C7EB" HorizontalAlignment="Left" Margin="-100,0,0,0" Width="100"/> 
      </Grid>        
     </Grid>                
    </Border> 

    <Border x:Name="roundBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="10" /> 
    <TextBlock /> 

    </Grid> 
</ControlTemplate> 

這導致:

enter image description here

凡Part_Indicator是左邊的LightBlue矩形(它的寬度在內部設置在PrograssBar控制,這裏看到的值爲20)和'roundBorder'。

我需要的是對的PART_Indicator到剪輯過roundBorder,導致類似這樣:

enter image description here

+2

檢查[這](http://stackoverflow.com/questions/5649875/wpf-how-to-make-the-border-trim-the-child-elements)的問題。它可能會幫助你 – dkozl

+0

BY THE WAY爲任何人看這個問題。下面的答案。可悲的是0票上漲。很棒。這是要走的路。沒有轉換器。基於控件的內容對模板沒有額外的影響。 簡單剪裁,同時保留。 –

回答

5

有一個ClipToBounds財產上Border應該剪輯的內容在該Border的界限,但是不幸的是,它並沒有「做它在錫說」:

<Border CornerRadius="25" BorderBrush="RoyalBlue" BorderThickness="3" Width="300" 
    Height="50" ClipToBounds="True"> <!-- This doesn't work as expected --> 
    <Rectangle Fill="SkyBlue" /> 
</Border> 

但是,Rectangle類也提供了一些可能有所幫助的屬性。有一些東西只是用Rectangle.RadiusXRectangle.RadiusY性質圓的邊角Rectangle?:

<Border CornerRadius="25" BorderBrush="RoyalBlue" BorderThickness="3" Width="300" 
    Height="50"> 
    <Rectangle RadiusX="23" RadiusY="23" Fill="SkyBlue" /> 
</Border> 

我知道你要裁剪的Rectangle的彩色填充阻止你,但你可以使用Rectangle.Clip屬性爲:

<Border CornerRadius="25" BorderBrush="RoyalBlue" BorderThickness="3" Width="300" 
    Height="50"> 
    <Grid> 
     <Rectangle Name="ClipRectangle" Fill="Green" Margin="50,0,0,0" 
      Visibility="Hidden" /> 
     <Rectangle RadiusX="23" RadiusY="23" Fill="SkyBlue" Clip="{Binding 
      RenderedGeometry, ElementName=ClipRectangle}" /> 
    </Grid> 
</Border> 

這剪輯有色Rectangle與其他RectangleRenderedGeometry命名ClipRectangle ...或者,當我說這款C嘴脣,也許我應該說這應該是剪輯,因爲我剛剛發現,這似乎只能在WPF設計器中運行,而不是在應用程序運行時運行。

enter image description here

不過,我出來的時候在這裏,所以希望你能找到拼圖的最後一塊,完成這個自己。潛在地,您也可以通過綁定到LinearGradientBrushGradientStop.Offset屬性來完成此操作,該屬性在Border上設置爲Background,因此您甚至不需要此方法的Rectangle。如果我以後可以再看,我會再看一次。


UPDATE >>>

我再看看這個Clip Rectangle而不能工作,爲什麼它只在Visual Studio設計的作品。所以,放棄這個想法,你可以試試LinearGradientBrush的想法,這同樣很好。首先,定義您的Brush

<LinearGradientBrush x:Key="ValueBrush" StartPoint="0,0" EndPoint="1,0"> 
    <GradientStop Offset="0.0" Color="SkyBlue" /> 
    <GradientStop Offset="0.7" Color="SkyBlue" /> 
    <GradientStop Offset="0.7" Color="Transparent" /> 
    <GradientStop Offset="1.0" Color="Transparent" /> 
</LinearGradientBrush> 

現在,我已經硬編碼的值,產生這樣的:

enter image description here

從剛纔這段代碼:

<Border CornerRadius="25" BorderBrush="RoyalBlue" Background="{StaticResource 
    ValueBrush}" BorderThickness="3" Width="300" Height="50" ClipToBounds="True" /> 

爲了您的實際需求,您需要創建一個double屬性,以將數據綁定到GradientStop.Offset屬性,如下所示:

<LinearGradientBrush x:Key="ValueBrush" StartPoint="0,0" EndPoint="1,0"> 
    <GradientStop Offset="0.0" Color="SkyBlue" /> 
    <GradientStop Offset="{Binding MidPoint}" Color="SkyBlue" /> 
    <GradientStop Offset="{Binding MidPoint}" Color="Transparent" /> 
    <GradientStop Offset="1.0" Color="Transparent" /> 
</LinearGradientBrush> 

現在,只要您提供介於0.0和1.0之間的值,就會創建您的電平表。

+0

這正是我所期待的,謝謝。 我會嘗試一下 –

+0

其實我不能讓它開始工作,我來試試,後來 +1分,而 –

2

我最終什麼事做:

控件模板:

  <ControlTemplate TargetType="{x:Type ProgressBar}"> 
       <Grid x:Name="TemplateRoot" SnapsToDevicePixels="true"> 

        <Rectangle x:Name="PART_Track" Fill="White" /> 

        <Border x:Name="roundBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="10"/> 

        <Border x:Name="PART_Indicator" HorizontalAlignment="Left"> 

         <Border.Clip> 
          <MultiBinding Converter="{x:Static common:UIConverters.BorderClipConverter}"> 
           <Binding Path="ActualWidth" ElementName="roundBorder" /> 
           <Binding Path="ActualHeight" ElementName="roundBorder" /> 
           <Binding Path="CornerRadius" ElementName="roundBorder" /> 
          </MultiBinding> 
         </Border.Clip> 

         <Grid x:Name="Foreground"> 
          <Rectangle x:Name="Indicator" Fill="{TemplateBinding Background}" /> 
          <Grid x:Name="Animation" ClipToBounds="true"> 
           <Rectangle x:Name="PART_GlowRect" Fill="#FF86C7EB" HorizontalAlignment="Left" Margin="-100,0,0,0" Width="100" /> 
          </Grid> 
         </Grid> 
        </Border> 

       </Grid>    
     </ControlTemplate> 

BorderClipConverter:(從Marat Khasanov answer)與使用OpacityMask在矩形

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

      var clip = new RectangleGeometry(new Rect(1.5, 1.5, width - 3, height - 3), 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(); 
    } 
} 
2

一個更好的解決一些微調除了放置在「MainGrid」中的OuterBorder之外的所有模板零件都使用不透明度蒙版進行剪裁,不透明度蒙版將其稱爲「MaskBorder」。

「TemplateRoot」存在用於PrograssBar控制的內部工作。

<ControlTemplate TargetType="{x:Type ProgressBar}"> 
     <Grid x:Name="TemplateRoot"> 
      <Border x:Name="OuterBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="10"> 
       <Grid> 
        <Border x:Name="MaskBorder" Background="{TemplateBinding Background}" CornerRadius="9.5" /> 

        <Grid x:Name="MainGrid"> 
         <Grid.OpacityMask> 
          <VisualBrush Visual="{Binding ElementName=MaskBorder}" />         
         </Grid.OpacityMask> 

         <Rectangle x:Name="PART_Track" Fill="White" /> 

         <Border x:Name="PART_Indicator" HorizontalAlignment="Left">         
          <Grid x:Name="Foreground"> 
           <Rectangle x:Name="Indicator" Fill="{TemplateBinding Background}" /> 
           <Grid x:Name="Animation" ClipToBounds="true"> 
            <Rectangle x:Name="PART_GlowRect" Fill="#FF86C7EB" HorizontalAlignment="Left" Margin="-100,0,0,0" Width="100" /> 
           </Grid> 
          </Grid> 
         </Border>                 
        </Grid>                                  

       </Grid>       
      </Border>      
     </Grid>      
    </ControlTemplate> 
+0

嗨@Sheridan,我發現了一個更好的解決方案,然後就是我了。 –