2

Dynamic Data Display には、MarkerPointsGraph というクラスがあります。これは FrameWorkElement から派生し (途中で一連の他のクラスを介して、最も直接的な親は PointsGraphBase になります)、OnRenderMethod をオーバーライドしてチャート上に一連のマーカーを描画します。

これは、画面上にレンダリングされるポイントごとに、適切なマーカー タイプ (たとえば、Triangle、Circle など) の render メソッドを 1 回呼び出すことによって行われます。これらのマーカーの 1 つにマウスが置かれたことを識別する方法を見つけて、そのマーカーのツールヒントを設定できるようにする必要があります。

ポイントを画面位置からビューポート位置、およびデータ位置に変換し、元に戻すことができる一連のメソッドがあります。つまり、画面値を対応するデータ値またはビューポート値に変換し、その逆も同様です。

また、このフレームワーク要素のツールヒントを開くイベントと、これらの各マーカーのピクセル サイズもあります。ユーザーが特定のマーカーにカーソルを合わせている限り、ユーザーがカーソルを合わせたポイントを特定し、markerpointsgraph にツールチップの値を設定させる必要があります。

ただし、値を変換するための変換とメソッドは、特に x 方向でうまく機能していないようです。y - 方向は問題ないようです。

以下は、アイデアを説明するサンプルコードです。

                    double selectedPointX = 0;
                    double selectedPointY = 0;

                    CoordinateTransform transformLocal = this.primaryPlotter.Transform;

                    if (series.SeriesDescription.YAxisAffinity == AxisAffinity_Y.Y1)
                    {
                        selectedPointX = Mouse.GetPosition(this.primaryPlotter).ScreenToViewport(transformLocal).X; //Getting the mouse positions
                        selectedPointY = Mouse.GetPosition(this.primaryPlotter).ScreenToViewport(transformLocal).Y;
                    }
                    else if (series.SeriesDescription.YAxisAffinity == AxisAffinity_Y.Y2 && injSecondaryAxis != null)
                    {
                        transformLocal = injSecondaryAxis.Transform;

                        selectedPointX = Mouse.GetPosition(this.injSecondaryAxis).ScreenToViewport(transformLocal).X;
                        selectedPointY = Mouse.GetPosition(this.injSecondaryAxis).ScreenToViewport(transformLocal).Y;
                    }
                    else if (series.SeriesDescription.YAxisAffinity == AxisAffinity_Y.Y3 && injTertiaryAxis != null)
                    {
                        transformLocal = injTertiaryAxis.Transform;

                        selectedPointX = Mouse.GetPosition(this.injTertiaryAxis).ScreenToViewport(transformLocal).X;
                        selectedPointY = Mouse.GetPosition(this.injTertiaryAxis).ScreenToViewport(transformLocal).Y;
                    }

                    foreach (var item in SeriesList)
                    {
                        if (item.Key == GraphKey)
                        {
                            for (int i = 0; i < item.Value.Collection.Count; i++)
                            {
//Calculate the size of the marker on the screen and allow for some level of inaccuracy in identifying the marker i.e anywhere within the marker is allowed. 
                                double xlowerBound = item.Value.Collection[i].DataToViewport(transformLocal).X - series.MarkerSize;
                                double xUpperBound = item.Value.Collection[i].DataToViewport(transformLocal).X + series.MarkerSize;
                                double ylowerBound = item.Value.Collection[i].DataToViewport(transformLocal).Y - series.MarkerSize;
                                double yUpperBound = item.Value.Collection[i].DataToViewport(transformLocal).Y + series.MarkerSize;

                                //If point is within bounds
                                if (!(selectedPointX < xlowerBound || selectedPointX > xUpperBound || selectedPointY < ylowerBound || selectedPointY > yUpperBound))
                                {
                                    strToolTip = item.Value.Collection[i].X + ", " + item.Value.Collection[i].Y; //This point is set as the tooltip
                                    break;
                                }
                            }

                            break;
                        }
                    }

ここで、injSecondary と injTertiary は、2 つの垂直 Y 軸を提供する 2 つの挿入されたプロッターです。これらは、プライマリ チャート プロッタと非常によく似た動作をします。

ここで何か問題が発生していますか?何らかの理由で、実際にクリックされたポイントよりかなり前のポイントが buffer 句を通過しています。

4

2 に答える 2

2

うーん、あなたはこれについて間違った方向に進んでいるようです。D3 のソース コードを掘り下げると、マーカー クラスの 1 つを開いて、そこでツールチップを直接編集できます。すべての System.Windows.Shapes 要素には、マーカー クラスで直接割り当てることができる Tooltip プロパティがあります。ツールチップが保持するデータを決定するだけです。

例 - CircleElementPointMarker クラス :

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;

namespace Microsoft.Research.DynamicDataDisplay.PointMarkers
{
/// <summary>Adds Circle element at every point of graph</summary>
public class CircleElementPointMarker : ShapeElementPointMarker {

    public override UIElement CreateMarker()
    {
        Ellipse result = new Ellipse();
        result.Width = Size;
        result.Height = Size;
        result.Stroke = Brush;
        result.Fill = Fill;
        if (!String.IsNullOrEmpty(ToolTipText))
        {
            ToolTip tt = new ToolTip();
            tt.Content = ToolTipText;
            result.ToolTip = tt;
        }
        return result;
    }

    public override void SetMarkerProperties(UIElement marker)
    {
        Ellipse ellipse = (Ellipse)marker;

        ellipse.Width = Size;
        ellipse.Height = Size;
        ellipse.Stroke = Brush;
        ellipse.Fill = Fill;

        if (!String.IsNullOrEmpty(ToolTipText))
        {
            ToolTip tt = new ToolTip();
            tt.Content = ToolTipText;
            ellipse.ToolTip = tt;
        }
    }

    public override void SetPosition(UIElement marker, Point screenPoint)
    {
        Canvas.SetLeft(marker, screenPoint.X - Size / 2);
        Canvas.SetTop(marker, screenPoint.Y - Size / 2);
    }
}
}

このクラスには、ツールチップを処理するコードが組み込まれていることがわかります。ToolTipText は、親クラスの ShapeElementPointMarker から派生するプロパティです。表示する必要があるデータをそのプロパティに割り当てるだけです。

于 2012-11-16T14:21:37.653 に答える
0

プロッターで Mouse.GetPosition の代わりに cursorcoordinategraph を使用して、正しい画面位置を取得し、ScreenToViewport 変換を回避します。また、境界の作成中に DataToScreen を使用します。

于 2012-11-17T06:38:53.817 に答える