WPF - 从PSD文件

时间:2015-09-09 20:08:10

标签: c# wpf wpf-controls

我开始使用WPF进行冒险,在创建第一个应用程序后,我想稍微设计一下。我找到UI template并使用Blend for VS2013我将PSD导入到我的项目中。

以下是ProgressBar在PSD中的外观: enter image description here

以下是导入Blend时的外观: enter image description here

这是代码:

    <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上找到类似的问题(snail progressbar除外,但解决方案是基于图像而不是路径)。

2 个答案:

答案 0 :(得分:1)

我准备了一个关于你的控制模板的原型。

首先,我创建了一个定义如下的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>

注意:代码可能需要一些改进,但至少是一个好的开始,当你在进度条中达到低值时图形看起来不是很漂亮但是你肯定可以改进基于控件的控件的图形你的需要。 我希望这可以帮助你。

答案 1 :(得分:1)

我在最后简化了代码并制定了可行的解决方案。

    <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上。您还可以自定义文本块样式以获得所需的效果。