编辑进度条形状 wpf
Edit progress bar shape wpf
我有一个进度条,其 ControlTemplate 如下所示,我想将进度条的值设置为一个数字,以便进度更新为该值。我参考了关于此 but don't know how to use the converter for my scenario. I also checked this 的公认答案,并且编辑 Rect 工作正常。但是我不能使用 Rectangle Geomerty。请帮忙。 (如果我删除下面 xaml 中的注释路径,它会创建一些填充容器的值。)这是我删除注释 xaml.
时的屏幕截图
<Window.Resources>
<ControlTemplate x:Key="ProgressBarPath" TargetType="ProgressBar">
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Stretch="Uniform">
<Canvas Name="Test" Width="100" Height="100" Canvas.Left="0" Canvas.Top="0">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Canvas.RenderTransform>
<Canvas.Resources/>
<Canvas Name="g40">
<!--<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path28"
Fill="Red">
<Path.Data>
<PathGeometry Figures="M35.1 57h-.2l-2.1 2.6-10 12.5c-2.1 2.7-5.2 6.2-4.3 9.5 1.7 6.1 7.6 6.1 11.8 6.1H50V57H35.7z" FillRule="NonZero"/>
</Path.Data>
</Path>-->
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path30" Fill="#FF333333">
<Path.Data>
<PathGeometry Figures="M30.8 87.7c-4.2 0-10.1 0-11.8-6.1-.9-3.3 2.2-6.8 4.3-9.5l10-12.5 2.1-2.6 5-6.3 1.6-2.1 1-1.3V17.5l-2.2-.2c-1.2-.1-2.1-1.1-2.1-2.4 0-1.3 1.1-2.4 2.4-2.4H50v-5h-9.2c-.9 0-1.7.3-2.2.4-2.8 1-4.9 3.8-4.9 7 0 3 1.8 5.6 4.4 6.7v24.2L29.3 57 16.7 72.8c-2.9 3.7-3.5 8.6-1.4 12.8 2 4.2 6.2 6.9 10.9 6.9H50v-4.8H30.8z" FillRule="NonZero"/>
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path32" Fill="#FF333333">
<Path.Data>
<PathGeometry Figures="M35.4 57l-2.1 2.6 2.1-2.6z" FillRule="EvenOdd"/>
</Path.Data>
</Path>
<!--<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path34"
Fill="Red">
<Path.Data>
<PathGeometry Figures="M64.3 57H50v30.7h19.2c4.2 0 10.7-.7 11.8-6.1.7-3.4-2.2-6.8-4.3-9.5l-10-12.5-2.1-2.6h-.3z"
FillRule="NonZero"/>
</Path.Data>
</Path>-->
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path36" Fill="#FF666666">
<Path.Data>
<PathGeometry Figures="M84.7 85.6c2-4.2 1.5-9.1-1.4-12.8L70.7 57l-8.8-11.1V21.7c2.6-1.1 4.4-3.8 4.4-6.8 0-4.1-3.3-7.4-7.4-7.4H50v5h8.9c1.3 0 2.4 1.1 2.4 2.5 0 1.2-.9 2.2-2.1 2.3l-2.2.2v29.8l1 1.3 1.6 2.1 7.1 8.9 10 12.5c2.1 2.7 5 6.1 4.3 9.5-1.1 5.3-7.6 6.1-11.8 6.1H50v4.8h23.9c4.6 0 8.8-2.6 10.8-6.9z" FillRule="NonZero"/>
</Path.Data>
</Path>
<!--Unknown tag: metadata-->
</Canvas>
</Canvas>
</Viewbox>
</ControlTemplate>
</Window.Resources>
<Grid HorizontalAlignment="Center" Margin="0 4 0 0">
<ProgressBar Template="{StaticResource ProgressBarPath}" Width="480" Height="102" Value="40" />
</Grid>
</Window>
如果条形是矩形,您可以利用 ProgressBar 的 built-in 机制改变形状以显示当前值。否则,您将需要自己实现该机制。
我认为 会对此给出很好的提示。比方说,您创建了一个名为“FlaskProgressBar”的自定义 ProgressBar。在这个 ProgressBar 的 CustomTemplate 中,
为轮廓的路径定义一个PathGeometry,并设置其Stroke
two-colored笔刷来绘制轮廓。
为空白区域的路径添加一个RectangleGeometry,并使用轮廓路径的Data
裁剪。
为显示当前值的填充区域的路径添加一个 RectangleGeometry 并裁剪它。将 RectangleGeomety 命名为“PART_Content”,以便可以从 code-behind.
中找到它
<ControlTemplate x:Key="FlaskProgressBarTemplate" TargetType="{x:Type local:FlaskProgressBar}">
<ControlTemplate.Resources>
<LinearGradientBrush x:Key="OutlineBrush" StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#FF333333" Offset="0.5"/>
<GradientStop Color="#FF666666" Offset="0.5"/>
<GradientStop Color="#FF666666" Offset="1"/>
</LinearGradientBrush>
</ControlTemplate.Resources>
<Grid>
<Grid Margin="6">
<!-- Draw outline -->
<Path x:Name="Outline"
StrokeThickness="8"
Stroke="{StaticResource OutlineBrush}">
<Path.Data>
<PathGeometry Figures="M 20,0 L 20,60 0,100 60,100 40,60 40,0 Z"/>
</Path.Data>
</Path>
<!-- Draw vacent area -->
<Path Data="{Binding Data, ElementName=Outline}"
Fill="{TemplateBinding Background}">
<Path.Clip>
<RectangleGeometry Rect="0,0,60,100"/>
</Path.Clip>
</Path>
<!-- Draw filled area -->
<Path Data="{Binding Data, ElementName=Outline}"
Fill="{TemplateBinding Foreground}">
<Path.Clip>
<RectangleGeometry x:Name="PART_Content" Rect="0,100,60,100"/>
</Path.Clip>
</Path>
</Grid>
</Grid>
</ControlTemplate>
在“FlaskProgressBar”中,找到名为“PART_Content”的 RectangleGeometry,当当前值更改时,更改其 Rect
的 Y
值以将其向上或向下移动。
[TemplatePart(Name = "PART_Content", Type = typeof(RectangleGeometry))]
public class FlaskProgressBar : ProgressBar
{
public FlaskProgressBar() : base()
{
ValueProperty.OverrideMetadata(typeof(FlaskProgressBar),
new FrameworkPropertyMetadata(0D, (d, e) => SetValue((FlaskProgressBar)d, (double)e.NewValue)));
}
private RectangleGeometry? _content;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_content = this.GetTemplateChild("PART_Content") as RectangleGeometry;
SetValue(this, Value);
}
private static void SetValue(FlaskProgressBar instance, double value)
{
if (instance._content is not null)
{
var rect = instance._content.Rect;
instance._content.Rect = new Rect(rect.X, rect.Height - value, rect.Width, rect.Height);
}
}
}
这个 ProgresBar 看起来像这样:
轮廓Path的PathGeometry实际设计完全由您决定。
我有一个进度条,其 ControlTemplate 如下所示,我想将进度条的值设置为一个数字,以便进度更新为该值。我参考了关于此
<Window.Resources>
<ControlTemplate x:Key="ProgressBarPath" TargetType="ProgressBar">
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Stretch="Uniform">
<Canvas Name="Test" Width="100" Height="100" Canvas.Left="0" Canvas.Top="0">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Canvas.RenderTransform>
<Canvas.Resources/>
<Canvas Name="g40">
<!--<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path28"
Fill="Red">
<Path.Data>
<PathGeometry Figures="M35.1 57h-.2l-2.1 2.6-10 12.5c-2.1 2.7-5.2 6.2-4.3 9.5 1.7 6.1 7.6 6.1 11.8 6.1H50V57H35.7z" FillRule="NonZero"/>
</Path.Data>
</Path>-->
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path30" Fill="#FF333333">
<Path.Data>
<PathGeometry Figures="M30.8 87.7c-4.2 0-10.1 0-11.8-6.1-.9-3.3 2.2-6.8 4.3-9.5l10-12.5 2.1-2.6 5-6.3 1.6-2.1 1-1.3V17.5l-2.2-.2c-1.2-.1-2.1-1.1-2.1-2.4 0-1.3 1.1-2.4 2.4-2.4H50v-5h-9.2c-.9 0-1.7.3-2.2.4-2.8 1-4.9 3.8-4.9 7 0 3 1.8 5.6 4.4 6.7v24.2L29.3 57 16.7 72.8c-2.9 3.7-3.5 8.6-1.4 12.8 2 4.2 6.2 6.9 10.9 6.9H50v-4.8H30.8z" FillRule="NonZero"/>
</Path.Data>
</Path>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path32" Fill="#FF333333">
<Path.Data>
<PathGeometry Figures="M35.4 57l-2.1 2.6 2.1-2.6z" FillRule="EvenOdd"/>
</Path.Data>
</Path>
<!--<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path34"
Fill="Red">
<Path.Data>
<PathGeometry Figures="M64.3 57H50v30.7h19.2c4.2 0 10.7-.7 11.8-6.1.7-3.4-2.2-6.8-4.3-9.5l-10-12.5-2.1-2.6h-.3z"
FillRule="NonZero"/>
</Path.Data>
</Path>-->
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path36" Fill="#FF666666">
<Path.Data>
<PathGeometry Figures="M84.7 85.6c2-4.2 1.5-9.1-1.4-12.8L70.7 57l-8.8-11.1V21.7c2.6-1.1 4.4-3.8 4.4-6.8 0-4.1-3.3-7.4-7.4-7.4H50v5h8.9c1.3 0 2.4 1.1 2.4 2.5 0 1.2-.9 2.2-2.1 2.3l-2.2.2v29.8l1 1.3 1.6 2.1 7.1 8.9 10 12.5c2.1 2.7 5 6.1 4.3 9.5-1.1 5.3-7.6 6.1-11.8 6.1H50v4.8h23.9c4.6 0 8.8-2.6 10.8-6.9z" FillRule="NonZero"/>
</Path.Data>
</Path>
<!--Unknown tag: metadata-->
</Canvas>
</Canvas>
</Viewbox>
</ControlTemplate>
</Window.Resources>
<Grid HorizontalAlignment="Center" Margin="0 4 0 0">
<ProgressBar Template="{StaticResource ProgressBarPath}" Width="480" Height="102" Value="40" />
</Grid>
</Window>
如果条形是矩形,您可以利用 ProgressBar 的 built-in 机制改变形状以显示当前值。否则,您将需要自己实现该机制。
我认为
为轮廓的路径定义一个PathGeometry,并设置其
Stroke
two-colored笔刷来绘制轮廓。为空白区域的路径添加一个RectangleGeometry,并使用轮廓路径的
Data
裁剪。为显示当前值的填充区域的路径添加一个 RectangleGeometry 并裁剪它。将 RectangleGeomety 命名为“PART_Content”,以便可以从 code-behind.
中找到它
<ControlTemplate x:Key="FlaskProgressBarTemplate" TargetType="{x:Type local:FlaskProgressBar}">
<ControlTemplate.Resources>
<LinearGradientBrush x:Key="OutlineBrush" StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#FF333333" Offset="0.5"/>
<GradientStop Color="#FF666666" Offset="0.5"/>
<GradientStop Color="#FF666666" Offset="1"/>
</LinearGradientBrush>
</ControlTemplate.Resources>
<Grid>
<Grid Margin="6">
<!-- Draw outline -->
<Path x:Name="Outline"
StrokeThickness="8"
Stroke="{StaticResource OutlineBrush}">
<Path.Data>
<PathGeometry Figures="M 20,0 L 20,60 0,100 60,100 40,60 40,0 Z"/>
</Path.Data>
</Path>
<!-- Draw vacent area -->
<Path Data="{Binding Data, ElementName=Outline}"
Fill="{TemplateBinding Background}">
<Path.Clip>
<RectangleGeometry Rect="0,0,60,100"/>
</Path.Clip>
</Path>
<!-- Draw filled area -->
<Path Data="{Binding Data, ElementName=Outline}"
Fill="{TemplateBinding Foreground}">
<Path.Clip>
<RectangleGeometry x:Name="PART_Content" Rect="0,100,60,100"/>
</Path.Clip>
</Path>
</Grid>
</Grid>
</ControlTemplate>
在“FlaskProgressBar”中,找到名为“PART_Content”的 RectangleGeometry,当当前值更改时,更改其 Rect
的 Y
值以将其向上或向下移动。
[TemplatePart(Name = "PART_Content", Type = typeof(RectangleGeometry))]
public class FlaskProgressBar : ProgressBar
{
public FlaskProgressBar() : base()
{
ValueProperty.OverrideMetadata(typeof(FlaskProgressBar),
new FrameworkPropertyMetadata(0D, (d, e) => SetValue((FlaskProgressBar)d, (double)e.NewValue)));
}
private RectangleGeometry? _content;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_content = this.GetTemplateChild("PART_Content") as RectangleGeometry;
SetValue(this, Value);
}
private static void SetValue(FlaskProgressBar instance, double value)
{
if (instance._content is not null)
{
var rect = instance._content.Rect;
instance._content.Rect = new Rect(rect.X, rect.Height - value, rect.Width, rect.Height);
}
}
}
这个 ProgresBar 看起来像这样:
轮廓Path的PathGeometry实际设计完全由您决定。