我需要创建一个圆ProgressBar
模板。
ControlTemplate:
<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>
这导致:
其中PART_Indicator
是左边的LightBlue矩形(其宽度在ProgressBar
控件内部设置,如此处所示,值为20)和roundBorder
。
我需要的是PART_Indicator
剪切roundBorder
,结果如下:
答案 0 :(得分:5)
ClipToBounds
类上有一个Border
属性,应该在Border
的范围内剪切内容,但不幸的是,它没有#39} ; t&#39;做它在锡上的说法:
<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.RadiusX
和Rectangle.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
与名为RenderedGeometry
的其他Rectangle
的{{1}}剪辑...或当我说此剪辑时,也许我应该说这应该剪辑,因为我发现这只能在WPF Designer中运行,而不是在应用程序运行时。
但是,我没有时间在这里,所以希望你能找到拼图的最后一块并自己完成。潜在地,您也可以通过数据绑定到ClipRectangle
的{{1}}属性来完成此操作,该属性设置为GradientStop.Offset
上的LinearGradientBrush
,因此您不会这个方法甚至需要Background
。如果我以后可以再看看。
更新&gt;&gt;&gt;
我再次查看了这个Border
,并且无法解释为什么它只适用于Visual Studio Designer。所以,放弃这个想法,你可以尝试Rectangle
想法,这同样是好的。首先,定义您的Clip Rectangle
:
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>
属性以将数据绑定到<Border CornerRadius="25" BorderBrush="RoyalBlue" Background="{StaticResource
ValueBrush}" BorderThickness="3" Width="300" Height="50" ClipToBounds="True" />
属性,如下所示:
double
现在,只要您提供介于0.0和1.0之间的值,就会创建您的电平表。
答案 1 :(得分:3)
使用OpacityMask更好的解决方案,除了放置在“MainGrid”中的OuterBorder之外的所有模板部件都使用不透明蒙板进行剪裁,该掩码由一个名为“MaskBorder”的对象设置。
对于PrograssBar控件的内部工作,存在“TemplateRoot”。
<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>
答案 2 :(得分:2)
我最终做了什么:
ControlTemplate:
<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)并在Rect
中进行了一些微调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();
}
}