7

我们的软件有时间线功能。它显示了几行小斑点,这些小斑点表示不同时间点的数据。代码是 c#、.Net 4 和 WPF。为了显示一个 blob,我们目前正在创建一个边框(给它一个画笔)并将其添加到网格中。然后将该网格添加到形成行的父网格中。

当时间线显示的 blob 数量相对较少时,这很好,但是当数据非常繁忙时,渲染会变慢,内存使用率上升,并且 UI 变得无响应。(毫不奇怪)。

我知道我们没有以最好的方式做到这一点 - 我的问题是在 wpf 中显示这样的图形的最佳方式是什么?

编辑:感谢您的回复 - 我将调查这些选项。然而,每个都需要大量的重新编码,我的问题更简单;是否有一些控制或效果可以用来替换资源成本较低的 Border?

4

3 回答 3

4

对于像这样的数据可视化,我真的很喜欢DynamicDataDisplay。该组件目前仅针对 Silverlight 进行维护/开发,但 WPF 有一个开源(链接中)版本,这确实是一个很棒的库。

该库使用IObservable集合并支持DateTime轴值。

有一个内置的标记图类型(下面的示例)。

您可以使用自定义标记,它支持缩放和滚动,以及许多其他不错的功能等。它也非常快,即使有相当大的数据集。

由于数据集是IObservable图表组件,因此图表组件会动态响应基础数据集中的变化,因此您的图表会在数据集合更新时随时更新。

编辑

这是一个例子:

用途:

using System.ComponentModel;
using Microsoft.Research.DynamicDataDisplay;
using Microsoft.Research.DynamicDataDisplay.Charts;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using Microsoft.Research.DynamicDataDisplay.PointMarkers;

主要的 :

 public Window1()
    {
        InitializeComponent();
        //
        const int N = 100;
        List<double> x = new List<double>();
        List<double> y = new List<double>();

        DateTimeAxis dtAxis = new DateTimeAxis();
        _plotter.HorizontalAxis = dtAxis;

        Random rand = new Random();
        for (int i = 0; i < N; i++)
        {   //generate some random data
            x.Add(dtAxis.ConvertToDouble(DateTime.Now.AddDays(i)));
            y.Add(rand.Next(N));
        }

        EnumerableDataSource<double> gX = new EnumerableDataSource<double>(x);
        EnumerableDataSource<double> gY = new EnumerableDataSource<double>(y);
        _MarkerGraph.DataSource = new CompositeDataSource(gX,gY);

        //no scaling - identity mapping
        gX.XMapping = xx => xx;
        gY.YMapping = yy => yy;

        CirclePointMarker mkr = new CirclePointMarker();
        mkr.Fill = new SolidColorBrush(Colors.Red);
        mkr.Pen = new Pen(new SolidColorBrush(Colors.Black),2.0);
        _MarkerGraph.Marker = mkr;
    }

XAML:

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d3="clr-namespace:Microsoft.Research.DynamicDataDisplay;assembly=DynamicDataDisplay"
Title="Window1" Height="481" Width="651">
<Grid>
    <d3:ChartPlotter Name="_plotter">
        <d3:MarkerPointsGraph Name="_MarkerGraph"/>
    </d3:ChartPlotter>
</Grid>

输出 : 程序运行...

DateTime 轴可以很好地缩放,调整天、月、小时、秒的刻度……只要合适。非常简单!

如果您确实使用此包,我强烈建议您下载源代码并将其作为第二个项目添加到您的解决方案中。D3 的文档非常糟糕,在项目中拥有源代码有助于弄清楚事情是如何工作的。如果需要,它还可以很容易地添加/扩展内容。如果您这样做,请务必引用您的解决方案中的项目,而不是编译的 DLL。

另请注意,许多可用的文档和在线示例都针对维护的 Silverlight 组件,而不是针对开放的 WPF 组件。这两个版本之间的许多组件都不同,因此您必须深入了解 WPF 组件以查看其中的内容。上面的示例适用于 v0.3 WPF 组件。

于 2012-04-16T15:59:57.067 回答
3

如果您想绘制大量不断变化的视觉效果,WPF 必须提供的最快方法是覆盖OnRender并绘制到DrawingContext.

如果视觉效果大部分是静态的,但有时会发生变化,最快的方法是DrawingVisual为每个视觉效果创建一个,然后可以根据需要进行修改。

此问题,链接文章和答案中的更多详细信息。

于 2012-04-16T16:14:22.187 回答
0

在我看来,drawingcontext 或 drawingvisual 有点慢和复杂

所以wpf的位图图像速度很快,可以试试,可以比drawingcontext或drawingvisual更快

实现代码;

public BitmapImage yuklenenResim;
public OpenFileDialog selectImage;

yuklenenResim = new BitmapImage();
yuklenenResim.BeginInit();
yuklenenResim.UriSource = new Uri(selectImage.FileName);
yuklenenResim.CacheOption = BitmapCacheOption.OnDemand;
yuklenenResim.EndInit();

/// imgSource is Image on wpf xaml side
imgSource.Source = yuklenenResim;
于 2021-04-29T11:10:57.240 回答