如何剪辑/塑造进度条

时间:2018-02-21 09:52:37

标签: c# wpf progress-bar

如何使用ViewModel中的属性剪切/整形ProgressBar指示符?

我想使用SliderProgressBar控件添加反馈指示符,其中我剪辑以便只显示一行圆圈。由于视图可以调整大小并且圆直径​​是固定的,我想将剪切的形状绑定到一个属性,指示要显示的圆圈数。

我尝试使用VisualBrush,其中我平铺了Elipse个形状。但最终是个别圈子被削减,这看起来并不好。

这里的圆圈是我想要达到的目的:

enter image description here

<ProgressBar x:Name="PART_FeedbackBar" Grid.Column="1" Grid.Row="1"
                Value="{Binding Path=Value}" 
                Maximum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                         AncestorType={x:Type Slider}}, Path=Maximum}"
                Minimum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                         AncestorType={x:Type Slider}}, Path=Minimum}" 
                Orientation="Horizontal"
                BorderThickness="0"
                Background="{StaticResource PrimaryColor}"
                Foreground="{StaticResource HighlightColor}"
                Height="20">
    <ProgressBar.Clip>
        <!-- What to add here? -->
    </ProgressBar.Clip>
</ProgressBar>

1 个答案:

答案 0 :(得分:0)

好吧,我找到了使用ProgressBar.OpacityMask而不是ProgressBar.Clip的解决方案,因为ProgressBar.OpacityMask支持VisualBrush。通过这种方式,我可以平铺Elipse,其中ProgressBar Opacity设置为0。

要将圈数设置为ProgressBar宽度,我添加了一个SizeChanged事件处理程序,用于计算Elipse个形状的数量。 VisualBrush Viewport属性绑定到Elipse计数属性,使用Converterint值转换为Rect

结果:

enter image description here

XAML:

<ProgressBar x:Name="PART_FeedbackBar" Grid.Column="1" Grid.Row="1" 
             SizeChanged="PART_FeedbackBar_SizeChanged"
             Value="{Binding Path=Value}" 
             Maximum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                       AncestorType={x:Type Slider}}, Path=Maximum}"
             Minimum="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                       AncestorType={x:Type Slider}}, Path=Minimum}" 
             Orientation="Horizontal"
             BorderThickness="0"
             Foreground="{StaticResource HighlightColor}"
             Background="{StaticResource PrimaryColor}"
             Height="15"
             Margin="25,10">
    <ProgressBar.OpacityMask>
        <VisualBrush x:Name="FeedbackBarOpacityMask" TileMode="Tile" 
                     Viewport="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
                             AncestorType={x:Type UserControl}}, Path=FeedbackDotCount, 
                             Converter={converters:IntegerToViewportConverter}}"
                     Stretch="Uniform">
            <VisualBrush.Visual>
                <Ellipse Height="1" Width="1" Fill="Black" />
            </VisualBrush.Visual>
        </VisualBrush>
    </ProgressBar.OpacityMask>
</ProgressBar>

SizeChanged事件处理程序:

private void PART_FeedbackBar_SizeChanged(object sender, SizeChangedEventArgs e)
{
    FeedbackDotCount = (int)Math.Ceiling(e.NewSize.Width / 25);
}

转换器:

public class IntegerToViewportConverter : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var count = (int)value;
        var viewport = new Rect(0, 0, 0, 1);
        if (count > 0)
        {
            viewport.Width = 1 / (double)count;
        }
        return viewport;       
    }

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

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}