Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - create ProgressBar template from PSD file

I'm starting my adventure with WPF and after creating my first application I want to style it a bit. I found UI template and using Blend for VS2013 I imported PSD into my project.

Here is how ProgressBar looks in PSD: enter image description here

and here is what it looks when imported to Blend: enter image description here

And here is code:

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

My problem is how can I convert that canvas to ProgressBar Template.

Based on tutorial I was able to create template, but there were rectangles not paths. I've tried using paths but I can't align them correctly.

How can I create Template that uses Path as PART_Track and PART_Indicator and how can I add text to that ProgressBar?

I imagine this as 3 layers: component background (orange one), progress background (brown) and progress bar (green). Maybe I should use two layers: progress bar and background with stroke?

This is my first template so I'd like to do it best I can.

I couldn't find similar question on SO (except snail progressbar, but there solution is based on images instead of paths).

like image 342
Misiu Avatar asked Sep 09 '15 20:09

Misiu


1 Answers

I prepared a protoype of how your control template can be.

Firstly I have created a IMultiValueConverter defined as followed:

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

Then I declared it as a resource in the wpf window (I omissis the declaration of the namespace):

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

Then I prepared a Style which applies the control template to all the ProgressBar in the window defined in this way:

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

Note: The code may need some improvements but at least is a good start, the graphics when you reach low values in the progress bar doesn't seem to be very beautiful but surely you can improve the graphic of the control based in your needings. I hope this helps you.

like image 57
Mattia Magosso Avatar answered Oct 08 '22 18:10

Mattia Magosso