0

グラフコントロールを作成しています。x軸とy軸のタリーラベルを追加するために行っているのは、各タリーマークにテキストブロックを追加し、そのタリーマークに関連する値を表示することです。

しかし、データベースからデータをロードし、テキストボルトを再度描画してグラフ領域を更新する必要がある場合、グラフペインに残っている古いテキストブロックを削除できません。

この問題を克服するために、テキストブロックをグループボックスの横に配置し、グラフペインを再描画してグループボックスの要素を削除し、再度配置することを考えました。

このアプローチは正しいですか?クラスの背後にあるコードのgroupboxに要素を配置する方法を教えてください。そして、彼らが私の問題に対する他の解決策であるかどうか教えてください。

よろしく、ランガナ。

4

1 に答える 1

1

WPFには、ほとんどの問題に対する多くの解決策があります。私はあなたの問題に対する3つの可能な解決策について議論します-あなたが説明するものと他の2つ。どちらが最適かを決めることができます。

解決策1:TextBlockオブジェクトを使用してラベルを表示する

があり、目盛りごとにをCanvas追加しているようです。TextBlockこれは、パフォーマンスがそれほど重要ではなく、データバインディングを使用できない場合に実行可能なソリューションです。

この場合、TextBlockを削除する方法は2つあります。

  1. List<TextBlock>ラベルを最後に作成したときに作成したTextBlockのすべてのTextblockリストを含めることができます。ラベルを再作成するときはいつでも、このリストを実行して、リスト上の各TextBlockを包含パネル(キャンバス)から削除してください。

  2. 新しいCanvasを作成してTextBlockを配置し、ラベルを変更するときにCanvas全体を削除できます。

少し効率的であるため、2番目の手法の例を次に示します。

class MyGraphBuilder
{
  Canvas _labelCanvas;
  ...
  void AddLabels()
  {
    // Remove old label canvas, if any
    if(_labelCanvas!=null)
      _graphCanvas.Children.Remove(_labelCanvas);

    // Add new label canvas
    _labelCanvas = new Canvas();
    _graphCanvas.Children.Add(_labelCanvas);

    // Create labels
    foreach(...)
    {
      ...
      _labelCanvas.Add(new TextBlock ...
    }
    ...

  }
}

解決策2:データバインディングを使用する

WPFでは、コードを1行も記述せずに、多くのグラフを作成できます。WPFに組み込まれているデータバインディングは、比較的複雑な棒グラフなどを作成するのに十分です。

データバインディングを使用して単純な棒グラフを作成する例を次に示します。

<ItemsControl ItemsSource="{Binding myData}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <DockPanel>
        <TextBlock Width="50" Text="{Binding Label}"/>
        <Rectangle VerticalAlignment="{Stretch}" Width="{Binding Value}">
          <Rectangle.LayoutTransform>
            <ScaleTransform ScaleX="10" /> <!-- Scale factor here, can be binding too -->
          </Rectangle.LayoutTransform>
        </Rectangle>
        <TextBlock Text="{Binding Value}" FontSize="8"/>
      </DockPanel>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

水平方向に配置された2番目のItemsControlを使用し、そのデータテンプレートを使用して固定幅で数字と目盛りを表示することにより、水平軸に数値ラベルを追加できます。

解決策3:低レベルの描画クラスを使用する

DrawingGroupオブジェクトを作成し、それにオブジェクトを追加GeometryDrawingしてグラフを作成しGlyphRunDrawingDrawingGroup内部に配置DrawingVisualしてメインに追加しますPanel

特定のブラシとペンを共有するアイテムのセットごとに1つGeometryDrawingまたは使用する必要があります。GlyphRunDrawingたとえば、軸と目盛りがすべて同じ色と幅であるGeometryDrawing場合は、それらすべてに対して1つを作成しますが、各目盛りが異なる色である場合は、複数のGeometryDrawingオブジェクトを作成します。

Geometryごとにオブジェクトを作成しますGeometryDrawing。最高の効率を得るには、を使用する必要がありますStreamGeometryが、他のGeometryクラスも適切に機能し、使いやすく、XAMLで初期化できます。PathGeometryまたはを作成することEllipseGeometryはおそらくすでにあなたに馴染みがあるので、私はの作成に焦点を合わせますStreamGeometryOpenこれを行うには、ステートメントでメソッドを呼び出してusing()から、返されたコンテキストに書き込みます。次に例を示します。

Geometry BuildAxesAndTicksGeometry()
{
  // First create geometry
  var geometry = new StreamGeometry();
  using(var context = geometry.Open())
  {
    // Horizontal axis
    context.BeginFigure(new Point(0,0), false, false);
    context.LineTo(new Point(_width, 0), true, false);

    // Vertical axis
    context.BeginFigure(new Point(0,0), false, false);
    context.LineTo(new Point(0, _height), true, false);

    // Horizontal ticks
    for(int i=0; i<_nTicksHorizontal; i++)
    {
      context.BeginFiture(new Point(i * _tickSpacing, -10), false, false);
      context.LineTo(new Point(i * _tickSpacing, 10), true, false);
    }
    // Do same for vertical ticks
  }

  // Now add it to a drawing
  return new GeometryDrawing { Geometry = geometry, Stroke = _axisPen };
}

Drawing BuildDrawing()
{
  var mainDrawing = new DrawingGroup();
  mainDrawing.Add(BuildAxesAndTicksGeometry());
  ... // Add other drawings, including one or more for the data
  return mainDrawing;
}

void UpdateDrawing()
{
  myDrawingVisual.Drawing = BuildDrawing();  // where myDrawingVisual is defined in the XAML
}

ソリューションの比較

ほとんどの場合、次の理由から、ソリューション2または3をお勧めします。

  • グラフがデータバインディングを使用できるほど単純な場合は、時間を大幅に節約できます。ソリューション2を使用します。
  • データバインディングを使用してグラフを作成できない場合、Drawingオブジェクトの使用は他の手法とほぼ同じくらい簡単であり、パフォーマンスを向上させることができます。ソリューション3を使用します。

あなたの場合、すでにソリューション1に多大な労力を費やしている場合は、おそらく最善ではないにしても、それを使い続けることをお勧めします。

于 2009-11-09T06:58:40.417 に答える