想要在进度条中添加 ItemsControl

问题描述 投票:0回答:1

我正在开发一个窗口,该窗口遵循预定步骤列表并显示步骤的进度。 这些要求基本上被简化为创建一个进度条,该进度条用通常的绿色指示正确的步骤,然后用红色指示不正确的步骤。 这些指示将随着每个执行的步骤而进展,并有可能散布绿色和红色指示。

我正在尝试使用带有嵌入式 ItemsControl 的 ProgressBar 元素来执行此操作。 我一直在收集有关如何创建此内容的示例,但没有运气。 我不完全理解 ItemsControl,并且可能没有以正确的方式处理这个问题。 这是我到目前为止所拥有的...

    <UserControl>
    <Grid>
        <ProgressBar x:Name="pb" Width="200" Height="15" Background="LightGray" Maximum="{Binding MaxVal}">
            <ProgressBar.Resources>
                <ItemsControl x:Name="icProgressBar" x:Key="icProgressBarKey" ItemsSource="{Binding}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Border x:Name="outerBorder" BorderBrush="Black" BorderThickness="1" Width="{Binding Percent}">
                                <Grid Background="{Binding PercentColor}">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                    </Grid.RowDefinitions>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="{Binding Percent}"/>
                                    </Grid.ColumnDefinitions>
                                </Grid>
                            </Border>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </ProgressBar.Resources>
        </ProgressBar>
    </Grid>
    </UserControl>

以及隐藏的代码...

        public ProgressBarWPF()
        {
            InitializeComponent();
            
            this.DataContext = new ObservableCollection<PercentItemsViewModel>()
            {
                new PercentItemsViewModel() { MaxVal = 30, Percent = 1.0, PercentColor = new SolidColorBrush(Colors.Green), Total = 0.0 },
                new PercentItemsViewModel() { MaxVal = 30, Percent = 1.0, PercentColor = new SolidColorBrush(Colors.Red), Total = 0.0 }
            };
        }

    public class PercentItemsViewModel : Utility.PropertyChangedNotification
    {
        public PercentItemsViewModel() { }

        public double Percent
        {
            get { return (GetValue(() => Percent)); }
            set { SetValue(() => Percent, value); }
        }

        public double Total
        {
            get { return (GetValue(() => Total)); }
            set { SetValue(() => Total, value); }
        }

        public int MaxVal
        {
            get { return (GetValue(() => MaxVal)); }
            set { SetValue(() => MaxVal, value); }
        }

        public Brush PercentColor
        {
            get { return (Brush)GetValue(() => PercentColor); }
            set { SetValue(() => PercentColor, value); }
        }
    }


PercentItemsViewModel 类是 INotifyPropertyChanged 接口的子类,它添加了 Notify 事件以及 GetValue 和 SetValue 调用。

当我运行此示例时,我没有得到任何好或坏的指示,并且当我执行定义的步骤时,进度条保持“空白”。 进度条的背景保持标准背景颜色。

我还尝试添加 ProgressBar 的 Value 属性的使用,但是当我推进该值时,进度条推进指示器,但它仍然是绿色的。 在上面的示例中,我删除了

Value={Binding Total}

我知道我可能走上了完全错误的道路,但在我看来,ItemsControl 将是满足此要求的完美方式。 对此的任何帮助将不胜感激。

c# wpf
1个回答
0
投票

仅使用 ItemsControl 来绘制 ProgressBar 就有点矫枉过正了。相反,您可以修改 ProgressBar 的

Foreground
来表示每个段。下面是一个扩展ProgressBar的简单示例。

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

public record Segment(int Value, Brush Brush);

public class SegmentedProgressBar : ProgressBar
{
    public Segment[] Segments
    {
        get { return (Segment[])GetValue(SegmentsProperty); }
        set { SetValue(SegmentsProperty, value); }
    }
    public static readonly DependencyProperty SegmentsProperty =
        DependencyProperty.Register(nameof(Segments), typeof(Segment[]), typeof(SegmentedProgressBar), new PropertyMetadata(null, OnSegmentsChanged));

    private static void OnSegmentsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var bar = (SegmentedProgressBar)d;

        var segments = (e.NewValue as Segment[])?.OrderBy(x => x.Value).ToArray();
        if (segments is not { Length: > 0 })
        {
            bar.Foreground = null;
            bar.Value = 0;
            return;
        }

        DrawingVisual drawingVisual = new DrawingVisual();
        DrawingContext drawingContext = drawingVisual.RenderOpen();

        int start = 0;

        foreach (var segment in segments)
        {
            drawingContext.DrawLine(
                pen: new Pen(segment.Brush, 1),
                point0: new Point(start, 0),
                point1: new Point(segment.Value, 0));

            start = segment.Value;
        }

        drawingContext.Close();

        bar.Foreground = new VisualBrush(drawingVisual);
        bar.Value = segments.Last().Value;
    }
}

将此 ProgressBar 的

Segments
依赖属性与视图模型中的 Segment 数组绑定。您可以根据需要填充数组。

Segment[] items = [
    new Segment(10, Brushes.Green),
    new Segment(20, Brushes.Orange),
    new Segment(40, Brushes.Red)];

要更新进度条,请设置新的 Segment 数组。

© www.soinside.com 2019 - 2024. All rights reserved.