我将为您介绍如何使用该模板制作可工作的进度条。
首先,我们创建自定义的WPF控件,并继承ProgressBar:
public class MyProgressBar : ProgressBar {
static MyProgressBar() {
DefaultStyleKeyProperty.OverrideMetadata(typeof (MyProgressBar), new FrameworkPropertyMetadata(typeof (MyProgressBar)));
}
}
接下来,我们进入Themes / Generic.xaml文件(如果不存在,则由Visual Studio为我们创建),并创建控件的外观:
<local:MyProgressBarWidthConverter x:Key="width" />
<Style TargetType="{x:Type local:MyProgressBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyProgressBar}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Viewbox Stretch="Fill">
<Canvas x:Name="Progress1" ClipToBounds="True" HorizontalAlignment="Left" Height="52" UseLayoutRounding="False" VerticalAlignment="Top" Width="493">
<Canvas x:Name="Loading" Height="52" Canvas.Left="0" Canvas.Top="0" Width="493">
<Path x:Name="Base2" Data="F1M22.086,3C22.086,3 63.118,4.562 125.833,3 199.069,1.175 294.072,5.645 370.146,4.333 430.323,3.294 474,3 474,3 479.523,3 487.826,8.208 489.687,15.098 491.864,23.156 491.191,28.867 489.081,37.118 487.415,43.637 479.856,47.999 474.333,47.999 474.333,47.999 368.324,50.176 252.792,47.999 135.568,45.792 42.104,49.541 23.518,47.999 12.306,47.07 6.028,45.811 4.028,37.787 3.199,34.461 1.441,23.222 7.178,11.906 10.179,5.987 16.563,3 22.086,3z" Height="52" Canvas.Left="0" Canvas.Top="0" Width="493" StrokeThickness="2">
<Path.Stroke>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFC18A13" Offset="1"/>
<GradientStop Color="#FFDC9A0C" Offset="0.339"/>
</LinearGradientBrush>
</Path.Stroke>
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFE4882D" Offset="0"/>
<GradientStop Color="#FFF5CA09" Offset="1"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Path x:Name="Bg" Data="F1M16.361,2.603C16.361,2.603 133.014,3.416 247.396,3.478 311.817,3.513 376.242,2.615 416.922,1.936 446.114,1.448 458.772,2.411 458.772,2.411 462.592,2.411 469.449,4.823 471.077,9.484 473.896,17.557 472.201,20.776 471.202,25.468 470.232,30.02 467.977,31.719 459.43,33.25 450.883,34.782 424.628,32.594 376,32.594 298.703,32.594 184.467,31.065 105.75,30.911 54.767,30.812 18.683,32.063 17.185,32.063 9.403,32.063 6.954,28.298 5.436,25.402 4.335,23.303 1.86,15.809 6.797,8.253 9.308,4.41 12.541,2.603 16.361,2.603z" Fill="#FFA77235" Height="36" Canvas.Left="9" Canvas.Top="8" Width="475"/>
<Viewbox Stretch="UniformToFill" Canvas.Left="8" Canvas.Top="7" Height="36">
<Viewbox.Width>
<MultiBinding Converter="{StaticResource width}">
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
</MultiBinding>
</Viewbox.Width>
<Path x:Name="Progress" Data="F1M19.986,2.29C19.986,2.29 50.058,4.582 104.021,2.936 154.279,1.403 214.797,4.02 264,4.02 310.844,4.02 341.117,2.457 347.659,2.936 354.201,3.415 356.173,5.804 357.743,10.484 359.313,15.162 360.055,20.568 357.202,26.468 355.175,30.658 353.597,31.417 347.492,33.396 345.484,34.047 309.622,34.937 262.208,34.943 217.536,34.948 162.63,33.886 116.105,33.683 61.905,33.446 19.087,34.063 17.185,34.063 9.403,34.063 6.016,31.048 4.498,28.152 3.397,26.053 1.86,15.809 6.797,8.253 9.308,4.41 16.166,2.29 19.986,2.29z" >
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF5DFF4E" Offset="0.409"/>
<GradientStop Color="#FF159308" Offset="1"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
</Viewbox>
</Canvas>
</Canvas>
</Viewbox>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
基本上,我们只需将您的psd中的整个画布放入Stretch = Fill的Viewbox中(并删除不必要的边距)。请注意,所有尺寸都相同且硬编码,但由于我们将控件放置在viewbox内,因此它将拉伸到viewbox的尺寸。而且,因为这是Stretch = Fill且没有指定宽度和高度的viewbox,所以它将拉伸到控件的大小。我们还将对应于绿色填充的路径放入其自己的viewbox中,因为我们需要根据ProgressBar.Value参数调整该路径的大小。
现在我们为绿色路径的viewbox宽度创建转换器:
public class MyProgressBarWidthConverter : IMultiValueConverter {
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
if (values.Any(c => c == null || c == DependencyProperty.UnsetValue))
return 0.0d;
var min = (double) values[0];
var current = (double) values[1];
var max = (double) values[2];
const double maxWidth = 475;
return (current/(max - min))*maxWidth;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
我们需要传入进度条的最小值、最大值和当前值,并计算绿色进度条的宽度。可用的最大宽度始终为475,但请记住我们已将其放在视口中,因此我们的控件宽度并非固定为475。
然后我们将控件放置在窗口中:
<wpf:MyProgressBar x:Name="bar" Width="500" Height="50" Value="5" Minimum="0" Maximum="100" />
代码后台:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
var timer = new DispatcherTimer()
{
Interval = TimeSpan.FromSeconds(1)
};
timer.Tick += (o, e) =>
{
if (bar.Value < bar.Maximum)
bar.Value++;
else
timer.Stop();
};
timer.Start();
}
}
我来演示一下进度条的工作方式。
一般来说,如果你的UI很复杂,你可能会想使用简单的表格,因为视图框中的许多路径并不是非常有效。但是如果你必须使用PSD中的固定路径……为什么不呢。
编辑以回答您的评论。当然,不需要创建新的控件,这只是更灵活的选择。如果你不想这样做,只需为你的进度条创建控件模板并将其分配给现有的ProgressBar.ControlTemplate,就像这样:
<Window x:Class="Wpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="clr-namespace:Wpf"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<wpf:MyProgressBarWidthConverter x:Key="width" />
<ControlTemplate x:Key="myProgressBar" TargetType="{x:Type ProgressBar}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Viewbox Stretch="Fill">
<Canvas x:Name="Progress1" ClipToBounds="True" HorizontalAlignment="Left" Height="52" UseLayoutRounding="False" VerticalAlignment="Top" Width="493">
<Canvas x:Name="Loading" Height="52" Canvas.Left="0" Canvas.Top="0" Width="493">
<Path x:Name="Base2" Data="F1M22.086,3C22.086,3 63.118,4.562 125.833,3 199.069,1.175 294.072,5.645 370.146,4.333 430.323,3.294 474,3 474,3 479.523,3 487.826,8.208 489.687,15.098 491.864,23.156 491.191,28.867 489.081,37.118 487.415,43.637 479.856,47.999 474.333,47.999 474.333,47.999 368.324,50.176 252.792,47.999 135.568,45.792 42.104,49.541 23.518,47.999 12.306,47.07 6.028,45.811 4.028,37.787 3.199,34.461 1.441,23.222 7.178,11.906 10.179,5.987 16.563,3 22.086,3z" Height="52" Canvas.Left="0" Canvas.Top="0" Width="493" StrokeThickness="2">
<Path.Stroke>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFC18A13" Offset="1"/>
<GradientStop Color="#FFDC9A0C" Offset="0.339"/>
</LinearGradientBrush>
</Path.Stroke>
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFE4882D" Offset="0"/>
<GradientStop Color="#FFF5CA09" Offset="1"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Path x:Name="Bg" Data="F1M16.361,2.603C16.361,2.603 133.014,3.416 247.396,3.478 311.817,3.513 376.242,2.615 416.922,1.936 446.114,1.448 458.772,2.411 458.772,2.411 462.592,2.411 469.449,4.823 471.077,9.484 473.896,17.557 472.201,20.776 471.202,25.468 470.232,30.02 467.977,31.719 459.43,33.25 450.883,34.782 424.628,32.594 376,32.594 298.703,32.594 184.467,31.065 105.75,30.911 54.767,30.812 18.683,32.063 17.185,32.063 9.403,32.063 6.954,28.298 5.436,25.402 4.335,23.303 1.86,15.809 6.797,8.253 9.308,4.41 12.541,2.603 16.361,2.603z" Fill="#FFA77235" Height="36" Canvas.Left="9" Canvas.Top="8" Width="475"/>
<Viewbox Stretch="UniformToFill" Canvas.Left="8" Canvas.Top="7" Height="36">
<Viewbox.Width>
<MultiBinding Converter="{StaticResource width}">
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
</MultiBinding>
</Viewbox.Width>
<Path x:Name="Progress" Data="F1M19.986,2.29C19.986,2.29 50.058,4.582 104.021,2.936 154.279,1.403 214.797,4.02 264,4.02 310.844,4.02 341.117,2.457 347.659,2.936 354.201,3.415 356.173,5.804 357.743,10.484 359.313,15.162 360.055,20.568 357.202,26.468 355.175,30.658 353.597,31.417 347.492,33.396 345.484,34.047 309.622,34.937 262.208,34.943 217.536,34.948 162.63,33.886 116.105,33.683 61.905,33.446 19.087,34.063 17.185,34.063 9.403,34.063 6.016,31.048 4.498,28.152 3.397,26.053 1.86,15.809 6.797,8.253 9.308,4.41 16.166,2.29 19.986,2.29z" >
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FF5DFF4E" Offset="0.409"/>
<GradientStop Color="#FF159308" Offset="1"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
</Viewbox>
</Canvas>
</Canvas>
</Viewbox>
</Border>
</ControlTemplate>
</Window.Resources>
<ProgressBar x:Name="bar" Width="500" Height="50" Value="5" Minimum="0" Maximum="100" Template="{StaticResource myProgressBar}"/>