在 WPF 列表视图中动态显示形状



我想在列表视图中可视化数据传输的进度。 一行是包含名称和状态的一次传输。 传输状态应以图形方式显示。 我想画一系列垂直线。一行表示传输段的状态,其颜色是段的状态(未传输、错误、传输完成)。

那么,如何在 WPF 中对此进行建模呢?我想将 WrapPanel 放入 XAML 中 GridViewColumn 内的 DataTemplate.CellTemplate 中。这就是我在网络教程方面取得的成就。 将单行放入 Canvas 到表中也可以,但如您所见,我需要它更加动态。

现在,我需要一些数据绑定来将不同数量的具有固定高度、一个像素宽度和可变颜色的线条形状放入 WrapPanel 中。我想到了 WrapPanel 是为了在窗口宽度小于需要显示的段数的情况下自动环绕该显示。

另外:如何告诉列表视图的最后一列占用窗口内的剩余空间?我不想要水平滚动条。

所有这些更新经常出现,两次更新之间可能不到一秒。所以我不想仅仅因为单个段改变其颜色而重新绘制所有内容。那么,在这种情况下如何访问单行?

好吧,我终于完成了我想看到的。首先,让我们了解一下 XAML。此处仅是具有 ListView 的部分,并且仅是包含段的单个列。当然,您需要一个窗口,并且可以添加更多列。

<ListView Name="KnownImages" ItemsSource="{Binding FileViewModels}">
<ListView.View>
<GridView>
<GridViewColumn Header="Segments" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="local:FileViewModel">
<ItemsControl Width="auto" Height="auto" ItemsSource="{Binding Segments}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="local:SegmentViewModel">
<Line ToolTip="{Binding ToolTip}" X1="1" X2="1" Y1="{Binding YTop}" Y2="15" StrokeThickness="3" Stroke="{Binding Stroke}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

主窗口有一个视图模型,其中包含

public ObservableCollection<FileViewModel> FileViewModels { get; set; }

ListView具有对该字段的绑定。DataTemplate有一个视图模型FileViewModel,其中包含列表视图中可视化一个文件的列表视图中单行的内容。它主要包含

public ObservableCollection<SegmentViewModel> Segments { get; set; }

因此,我们可以将ItemsControl绑定到该字段SegmentsItemsPanelTemplate内的WrapPanel现在填充了一个知道其数据类型SegmentViewModelDataTemplate

/// <summary>
/// View model of a single file segment, which is represented with
/// a vertical line. The changeable parts of the line are stored here
/// and are directly derived from the state of the segment in the
/// constructor (ToolTip, Color and the upper Y coordinate of the line)
/// </summary>
public class SegmentViewModel
{
private const int YTopEof=0;
private const int YTopIntermediate=3;
public string ToolTip { get; set; }
public Brush Stroke { get; set; }
public int YTop { get; set; }
/// <summary>
/// Derive appearance of the line from the business data received from queue
/// if we already received data for the segment.
/// </summary>
/// <param name="fromQ">our knowledge about the segment state</param>
public SegmentViewModel(SegmentState fromQ)
{
var sb = new StringBuilder();
sb.Append("Seg ");
sb.Append(fromQ.Number);
if (fromQ.IsInMemory)
sb.Append(", in memory");
if (fromQ.IsOnDisk)
sb.Append(", on disk");
if (!fromQ.IsComplete)
sb.Append(", INCOMPLETE!!!");
ToolTip = sb.ToString();
Color col;
if (!fromQ.IsComplete)
col = Colors.Magenta;
else if (fromQ.IsInMemory)
col = fromQ.IsOnDisk ? Colors.Black : Colors.Green;
else
col = fromQ.IsOnDisk ? Colors.RoyalBlue : Colors.Brown;
Stroke = new SolidColorBrush(col);
YTop = fromQ.EndOfFile ? YTopEof : YTopIntermediate;
}
/// <summary>
/// This constructor is for segments that we did not receive so far.
/// </summary>
/// <param name="segmentNumber">We only know that we expect data from this index.</param>
public SegmentViewModel(int segmentNumber)
{
ToolTip = $"Seg {segmentNumber} not yet seen";
YTop = YTopIntermediate;
Stroke = new SolidColorBrush(Colors.LightGray);
}

对于Segments数组中的每个SegmentViewModel实例,我们都会得到一个新的Line实例作为可视化。变量可视属性使用绑定(工具提示、颜色、行长)进行映射。非可变视觉对象属性是 XAML 中的常量。注意:坐标不是像素,而是更小的东西 - 至少在我的屏幕上。

最新更新