2012-04-16 11 views
7

私たちは、当社のソフトウェアのタイムライン機能を持っています。それは、異なる時点でデータを示す小さなブロブの行を示す。コードはc#、.Net 4、WPFです。ブロブを表示するには、現在、境界線(にブラシを付けて、)を作成し、グリッドに追加しています。このグリッドは、行を形成する親グリッドに追加されます。WPFでグラフィックを効率的に表示するには?

タイムラインに比較的少数のブロブが表示されていても、データが非常に混雑しているとレンダリングが遅くなり、memの使用率が上がり、UIが応答しなくなります。 (驚くことではないが)。

私はこれを最善の方法でやっていないことを知っています。私の質問は、このようなグラフィックをwpfで表示する最良の方法は何ですか?

編集:下記の返信いただきありがとうございます - これらのオプションを調査いたします。しかし、それぞれには大量の記録が必要です。私の質問はもっとシンプルです。より低いリソースコストであるBorderを置き換えるために使用できるいくつかのコントロールや効果はありますか?

+0

プログラムで要素を作成し、それをグリッドに追加するべきではありません。あなたのblobのためのlistItemデータ型を作成し、blobのコレクションをlistViewにバインドする必要があります。 – Alain

+0

スムーズにスクロールするのは非常に難しいでしょうか?私はすべてのデータをコレクションに追加するか(クラッシュする)、コレクションを動的に再作成する必要があります。これはおそらくスムーズに見えません。 – Sugrue

答えて

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コンポーネントではなく、多くの利用可能なドキュメントとオンラインサンプルが対象となっています。これらの2つのバージョンではコンポーネントの多くが異なるため、WPFコンポーネントを調べてそこにあるものを確認する必要があります。上の例はv0.3 WPFコンポーネントの例です。

+0

ありがとうございました。興味深い、私はいつかそれを使用するかもしれません。私は現在のシステムを根本的に再コード化する必要はないと思っています。それは99%働いています、私はちょうど実際にレンダリングをより効率的にしたいと思います。 – Sugrue

+0

@Sugrue私はレンダリングをより効率的にするためには、とにかくあなたのアプローチを変更する必要があると思います。すべての要素を単一のキャンバスに描画することは、おそらく、望ましいパフォーマンスを得るために必要であり、それは使用しているグリッド・イン・グリッド・アプローチからシフトしていることになります。あなたのデータが既にソートされている限り、実際にはチャートコンポーネントをドロップして一緒にリンクするのは非常に速いです。 –

+0

@Sugrue:これがどれほど簡単かを示す例を追加しました!実際、このコンポーネントは非常に効率的なデータレンダリングエンジンであり、解決しようとしている問題です。データを変換するためのいくつかの行を除いて、ほとんどのドロップインソリューションでなければなりません。 –

3

常に変化するビジュアルをたくさん描画したい場合は、WPFが提供する最速の方法はOnRenderをオーバーライドし、DrawingContextに描画することです。

ビジュアルがほとんど静的であることがありますが、時々変更される可能性がある場合は、最も速い方法は、それぞれに対してDrawingVisualを作成し、必要に応じて変更することです。

詳細はthis question、リンクされた記事と回答。

+0

ありがとう、私はそれを調査します。 – Sugrue

関連する問題