WPF - создать шаблон ProgressBar из файла PSD

Я начинаю свое приключение с WPF, и после создания своего первого приложения я хочу немного его подстроить. Я нашел шаблон пользовательского интерфейса и используя Blend для VS2013, я импортировал PSD в свой проект.

Вот как выглядит ProgressBar в PSD: введите описание изображения здесь

и вот что выглядит при импорте в Blend: введите описание изображения здесь

И вот код:

    <Canvas x:Name="Progress1" ClipToBounds="True" HorizontalAlignment="Left" Height="52" UseLayoutRounding="False" VerticalAlignment="Top" Width="493" Margin="0,307.5,0,-53.5">
        <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"/>
            <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" Height="36" Canvas.Left="8" Canvas.Top="7" Width="362">
                <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>
        </Canvas>
    </Canvas>

Моя проблема заключается в том, как преобразовать этот холст в шаблон ProgressBar.

На основе учебника мне удалось создать шаблон, но были прямоугольники, а не пути. Я пробовал использовать пути, но я не могу правильно их выровнять.

Как создать шаблон, который использует Path как PART_Track и PART_Indicator, и как я могу добавить текст к этому ProgressBar?

Я представляю это как 3 слоя: компонентный фон (оранжевый), фон прогресса (коричневый) и индикатор выполнения (зеленый). Может быть, я должен использовать два слоя: индикатор выполнения и фон с инсультом?

Это мой первый шаблон, поэтому я бы хотел сделать все, что мог.

Я не мог найти аналогичный вопрос о SO (кроме индикаторной панели улитки, но решение основано на образах вместо путей).

Ответ 1

Я дам вам представление о том, как вы можете сделать рабочий индикатор выполнения этого шаблона.

Сначала мы создаем пользовательский контроль 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 с Stretch = Fill и без указанной ширины и высоты - он будет растягиваться до размера элемента управления. Мы также добавляем Path, который соответствует зеленому заполнению, к его собственному viewbox, потому что нам нужно будет изменить размер этого Path в соответствии с параметром ProgressBar.Value.

Теперь мы создаем конвертер для зеленой ширины окна просмотра. Ширина:

 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; // that is from template
        return (current/(max - min))*maxWidth;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
        throw new NotImplementedException();
    }
}

Мы пропускаем Minimum, Value, Maximum индикатора выполнения и вычисляем ширину зеленой полосы. Максимальная доступная ширина всегда равна 475, но помните, что мы помещаем это в viewbox, поэтому наш элемент управления не привязан к ширине 475.

Затем мы устанавливаем управление в окне:

 <wpf:MyProgressBar x:Name="bar" Width="500" Height="50" Value="5" Minimum="0" Maximum="100" />

Codebehind:

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();
    }
} 

И посмотрим, как работает наш прогресс. В общем, если у вас большой пользовательский интерфейс, вы можете работать с простыми формами, потому что многие пути в видовых боксах не очень эффективны. Но если вам нужно работать с фиксированными путями из PSD... Почему бы и нет.

EDIT, чтобы ответить на ваш комментарий. Уверен, что не требуется создавать новый элемент управления, он просто более гибкий. Если вы не хотите этого делать, просто создайте шаблон управления для своего индикатора выполнения и назначьте существующий файл 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}"/>

Ответ 2

Я подготовил протопип о том, как ваш шаблон управления может быть.

Во-первых, я создал IMultiValueConverter, определенный следующим образом:

[ValueConversion(typeof(double), typeof(double))]
public class RatioConveter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (System.Convert.ToDouble(values[0]) * System.Convert.ToDouble(values[1])) / System.Convert.ToDouble(values[2]);
    }

    public object[] ConvertBack(object value, Type[] targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Затем я объявил его ресурсом в окне wpf (я объявляю объявление пространства имен):

<yourNamespace:RatioConveter x:Key="ratioConverter" />

Затем я подготовил Style, который применяет шаблон управления ко всем ProgressBar в окне, определенном таким образом:

<Style x:Key="{x:Type ProgressBar}"
           TargetType="{x:Type ProgressBar}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ProgressBar}">
                    <Grid x:Name="Container"  Height="{TemplateBinding Height}" Width="{TemplateBinding Width}">                            
                        <Canvas x:Name="Progress1" ClipToBounds="True" HorizontalAlignment="Left" Height="52" Width="493" UseLayoutRounding="False" VerticalAlignment="Top" Margin="0" >
                            <Canvas.Resources>
                                <system:Double x:Key="ratioConstant">1</system:Double>
                            </Canvas.Resources>
                            <Canvas.RenderTransform>
                                <ScaleTransform CenterX="0"
                                                CenterY="0">
                                    <ScaleTransform.ScaleX>
                                        <MultiBinding Converter="{StaticResource ResourceKey=ratioConverter}">
                                            <Binding ElementName="Container" Path="ActualWidth"/>
                                            <Binding Source="{StaticResource ratioConstant}"/>
                                            <Binding ElementName="Progress1" Path="Width"/>
                                        </MultiBinding>
                                    </ScaleTransform.ScaleX>
                                    <ScaleTransform.ScaleY>
                                        <MultiBinding Converter="{StaticResource ResourceKey=ratioConverter}">
                                            <Binding ElementName="Container" Path="ActualHeight"/>
                                            <Binding Source="{StaticResource ratioConstant}"/>
                                            <Binding ElementName="Progress1" Path="Height"/>
                                        </MultiBinding>
                                    </ScaleTransform.ScaleY>
                                </ScaleTransform>
                            </Canvas.RenderTransform>
                            <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"/>
                            <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" Height="36" Canvas.Left="8" Canvas.Top="7" Width="362">
                                <Path.Resources>
                                    <system:Double x:Key="ratioConstant">27500</system:Double>
                                </Path.Resources>
                                <Path.RenderTransform>
                                    <ScaleTransform CenterX="0"
                                                CenterY="0">
                                        <ScaleTransform.ScaleX>
                                            <MultiBinding Converter="{StaticResource ResourceKey=ratioConverter}">
                                                <Binding Path="Value" RelativeSource="{RelativeSource TemplatedParent}"/>
                                                <Binding ElementName="Progress" Path="Width"/>
                                                <Binding Source="{StaticResource ratioConstant}"/>
                                            </MultiBinding>
                                        </ScaleTransform.ScaleX>
                                    </ScaleTransform>
                                </Path.RenderTransform>
                                <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>
                        </Canvas>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Background">
            <Setter.Value>
                <LinearGradientBrush EndPoint="0,1"
                                     StartPoint="0,0">
                    <GradientStop Color="{DynamicResource ControlLightColor}"
                                  Offset="0" />
                    <GradientStop Color="{DynamicResource ControlMediumColor}"
                                  Offset="1" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="Foreground">
            <Setter.Value>
                <LinearGradientBrush EndPoint="0.5,1"
                                     StartPoint="0.5,0">
                    <GradientStop Color="{DynamicResource ControlMediumColor}"
                                  Offset="0" />
                    <GradientStop Color="{DynamicResource ControlDarkColor}"
                                  Offset="1" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>

Примечание. Коду могут потребоваться некоторые улучшения, но, по крайней мере, это хороший старт, графика, когда вы достигаете низких значений в индикаторе выполнения, кажется, не очень красива, но вы можете улучшить графику элемента управления, базирующегося на ваши потребности. Я надеюсь, это поможет вам.

Ответ 3

Я упростил ваш код в конце и разработал рабочее решение.

    <Window.Resources>
    <LinearGradientBrush x:Key="PressedBrush" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FFC18A13" Offset="1"/>
        <GradientStop Color="#FFDC9A0C" Offset="0.339"/>
    </LinearGradientBrush>
    <LinearGradientBrush x:Key="SolidBorderBrush" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FFE4882D" Offset="0"/>
        <GradientStop Color="#FFF5CA09" Offset="1"/>
    </LinearGradientBrush>
    <LinearGradientBrush x:Key="DarkBrush" EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
        <GradientStop Color="#FF5DFF4E" Offset="0.409"/>
        <GradientStop Color="#FF159308" Offset="1"/>
    </LinearGradientBrush>
    <Style x:Key="{x:Type ProgressBar}" TargetType="{x:Type ProgressBar}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ProgressBar}">

                    <Grid MinHeight="24" MinWidth="100">



                        <Border Name="PART_Track" CornerRadius="15" Background="{StaticResource PressedBrush}"  BorderThickness="10">
                            <Border.BorderBrush>
                                <VisualBrush>
                                    <VisualBrush.Visual>
                                        <Grid>

                                            <Path x:Name="path1" Stretch="Fill" Stroke="Black" Fill="{StaticResource SolidBorderBrush}" Width="Auto" Height="Auto" 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"></Path>
                                        </Grid>
                                    </VisualBrush.Visual>
                                </VisualBrush>
                            </Border.BorderBrush>
                        </Border>
                        <Border Name="PART_Indicator"  CornerRadius="15" Background="{StaticResource DarkBrush}"  HorizontalAlignment="Left" BorderThickness="10">
                            <Border.BorderBrush>
                                <VisualBrush>
                                    <VisualBrush.Visual>
                                        <Grid>
                                            <Path x:Name="path" Stretch="Fill"  Fill="Transparent" Width="Auto" Height="Auto" 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"></Path>
                                        </Grid>
                                    </VisualBrush.Visual>
                                </VisualBrush>
                            </Border.BorderBrush>
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

Только для завершения этого примера

<Grid Width="500" Height="100">
    <ProgressBar Height="61" Value="20" x:Name="sampleProgressBar"  />
    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ElementName=sampleProgressBar,Path=Value}"/>
</Grid>

Теперь вы можете установить индикатор выполнения, и его значение будет отражено в TextBlock. Вы также можете настроить стиль текстового блока, чтобы получить желаемый эффект.