有没有一种在WPF中实现这样的控件的最佳方法?

我可以轻松地复制文本标签和进度条(没有每个标签上方的圆形"凸起"),但我想知道是否已经有一个控件,或者是最佳实践,用于在WPF中创建这种控件.
Fre*_*lad 73
在这种情况下很难说最佳实践是什么,但这是我将如何做到这一点.
屏幕截图中的向导控件看起来像是a ProgressBar和a的组合,ItemsControl在这种情况下,我似乎ItemsControl比从其他方式更容易派生和实现进度功能,但这也取决于你希望它如何工作(如果你想要一个平稳的进展,或者只是逐个点亮点.
使用UniformGridas ItemsPanel和ItemTemplateunder,我们得到以下外观(Steps是一个List字符串)

<ItemsControl ItemsSource="{Binding Steps}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Rows="1"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Ellipse HorizontalAlignment="Center" Height="20" Width="20" Stroke="Transparent" Fill="Blue"/>
                <TextBlock Grid.Row="1" Text="{Binding}" HorizontalAlignment="Center" Margin="0,5,0,0"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
添加DropShadowEffect到ItemsPanel两个Path元素的ItemTemplate两个DataTriggers,以确定当前的产品显示/隐藏左/右侧的第一个或最后一个项目Path,我们可以得到一个非常相似的外观到您的截图

ItemsPanel
<UniformGrid Rows="1" SnapsToDevicePixels="True">
    <UniformGrid.Effect>
        <DropShadowEffect Color="Black"
                          BlurRadius="5"
                          Opacity="0.6"
                          ShadowDepth="0"/>
    </UniformGrid.Effect>
</UniformGrid>
ItemTemplate中
<DataTemplate>
    <DataTemplate.Resources>
        <Style TargetType="Path">
            <Setter Property="Data" Value="M0.0,0.0 L0.0,0.33 L1.0,0.33 L1.0,0.66 L0.0,0.66 L0.0,1.0"/>
            <Setter Property="StrokeThickness" Value="0"/>
            <Setter Property="Height" Value="21"/>
            <Setter Property="Stretch" Value="Fill"/>
            <Setter Property="Fill" Value="{StaticResource wizardBarBrush}"/>
            <Setter Property="StrokeEndLineCap" Value="Square"/>
            <Setter Property="StrokeStartLineCap" Value="Square"/>
            <Setter Property="Stroke" Value="Transparent"/>
        </Style>
    </DataTemplate.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Path Name="leftPath"/>
        <Path Name="rightPath" Grid.Column="1"/>
        <Ellipse Grid.ColumnSpan="2" HorizontalAlignment="Center" Height="20" Width="20" Stroke="Transparent" Fill="{StaticResource wizardBarBrush}"/>
        <TextBlock Grid.ColumnSpan="2" Grid.Row="1" Text="{Binding}" HorizontalAlignment="Center" Margin="0,5,0,0"/>
    </Grid>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}"
                     Value="{x:Null}">
            <Setter TargetName="leftPath" Property="Visibility" Value="Collapsed"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={markup:IsLastItemConverter}}"
                     Value="True">
            <Setter TargetName="rightPath" Property="Visibility" Value="Collapsed"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>
如果你决定使用这种方法,你可能会弄清楚如何让其余部分继续下去,比如
DropShadowEffect进度部分的stroke()而不是文本无论如何,我上传了一个带有自定义控件的示例项目WizardProgressBar和一个使用它的演示项目:https://www.dropbox.com/s/ng9vfi6uwn1peot/WizardProgressBarDemo2.zip?dl=0
看起来像这样

关于样本的注意事项
DropShadowEffect在进度部分和标题上获得或在每个项目之间得到一条细线(如图所示).我想不出一个简单的方法来摆脱它所以也许这毕竟不是最好的方法:)更新
对示例项目进行了一些更改,我将演示文稿分成两部分,ItemsControls以消除每个项目之间的细线.它现在看起来像这样

在这里上传:https://www.dropbox.com/s/ng9vfi6uwn1peot/WizardProgressBarDemo2.zip? dl =0
更新结束
以下是上面示例代码中缺少的部分
<LinearGradientBrush x:Key="wizardBarBrush" StartPoint="0.5,0.0" EndPoint="0.5,1.0">
    <GradientStop Color="#FFE4E4E4" Offset="0.25"/>
    <GradientStop Color="#FFededed" Offset="0.50"/>
    <GradientStop Color="#FFFCFCFC" Offset="0.75"/>
</LinearGradientBrush>
IsLastItemConverter
public class IsLastItemConverter : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        ContentPresenter contentPresenter = value as ContentPresenter;
        ItemsControl itemsControl = ItemsControl.ItemsControlFromItemContainer(contentPresenter);
        int index = itemsControl.ItemContainerGenerator.IndexFromContainer(contentPresenter);
        return (index == (itemsControl.Items.Count - 1));
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
    public IsLastItemConverter() { }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}