如何在WPF中有效地显示图形?

时间:2012-04-16 15:50:43

标签: c# .net wpf graphics

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

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

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

编辑:感谢您下面的回复 - 我会调查这些选项。但是每个都需要大量的重新编码,我的问题更简单;是否有一些控制或效果我可以用来取代资源成本较低的边界?

3 个答案:

答案 0 :(得分: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>

输出: Program runs...

DateTime轴可以很好地缩放,调整天数,月数,小时数,秒数......以及任何合适的数据。很容易就是馅饼!

如果您确实使用此软件包,我高度建议下载源代码并将其作为第二个项目添加到您的解决方案中。 D3的文档非常差,项目中的源代码有助于弄清楚工作原理。如果需要,它还可以很容易地添加/扩展内容。如果执行此操作而不是编译的DLL,请务必参考解决方案中的项目。

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

答案 1 :(得分:3)

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

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

this question中的更多详细信息,链接文章和答案。

答案 2 :(得分:0)

在我看来, 绘图上下文或绘图视觉有点缓慢和复杂

所以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;