我正在开发一个窗口,该窗口遵循预定步骤列表并显示步骤的进度。 这些要求基本上被简化为创建一个进度条,该进度条用通常的绿色指示正确的步骤,然后用红色指示不正确的步骤。 这些指示将随着每个执行的步骤而进展,并有可能散布绿色和红色指示。
我正在尝试使用带有嵌入式 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 将是满足此要求的完美方式。 对此的任何帮助将不胜感激。
仅使用 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 数组。