在 DataVisualization.Charting 中绘制轴并防止选择

Axis drawing over point and preventing selection in DataVisualization.Charting

我正在使用圆形标记来指示数据点的位置。当这些点绘制在一个轴上时,我不能 select 它们(使用 HitTest)...但是当它们被绘制在图表上的其他任何地方时我可以 select 它们。无法select 的点似乎在 轴下方绘制。如果我使标记变大,那么我可以通过单击圆的边缘 select 轴上的点。

有没有办法让标记绘制在轴的顶部(如果这是问题所在!)?

这真是个好问题。

这个问题确实存在我不知道一个简单的解决方案。

  • 这是一种可能的解决方法:

当你发现你击中了AxisAxisLabelTickMark时,你可以修改你测试的X。计算位置镜像在轴偏移的宽度,然后再次测试。

为此,您需要知道以像素为单位的轴位置及其宽度。

后者是axis.Linewidth。对于前者使用轴函数ax.ValueToPixelPosition。它采用 y 轴位置的 x 值。这将是 x 轴的最小值(如果已设置)或 0 或某个自动值,具体取决于您的数据。

这确实改善了这种情况,尽管我发现 TickMarks 仍然会阻碍,但不确定为什么。

如果鼠标点真的很近,用户会喜欢它,直到它们再次离开。您可以使用反向函数 PixelPositionToValue 和一些 Linq 来找到最近的点。

更新:

  • 事实上,最后一个想法可以作为替代解决方法来实施。

这是一个函数示例,用于查找最近点,可能在 MouseMove 事件中,或者可能在 HitTest 击中轴或轴元素之后..:[=​​32= ]

DataPoint GetNearestPoint(Series s, ChartArea ca, Point pt)
{
    int limit = s.MarkerSize * 4;  // pick a suitable distance!

    Axis ay = ca.AxisY;
    Axis ax = ca.AxisX;

    var mins = s.Points.Cast<DataPoint>().Select((x, index) =>
        new
        {
            val = Math.Abs(pt.Y - (int)ay.ValueToPixelPosition(x.YValues[0]))
                    +  Math.Abs(pt.X - (int)ax.ValueToPixelPosition(x.XValue)),
            ix = index
        });

    var min = mins.Where(x => x.val == mins.Min(v => v.val)).Select(x => x.ix).First();
    if (mins.ElementAt(min).val > limit) return null;
    else return s.Points[min];
}

这是我在创建 class 级别变量后调用它的方式:

DataPoint lastHit = null;

它会在光标足够近时为最近的点着色..:[=​​32=]

    var nearest = GetNearestPoint(someSeries, someChart.ChartAreas[0], e.Location);
    if (lastHit != null) lastHit.MarkerColor =  someSeries.Color;
    if (nearest != null)
    {
        lastHit = nearest;
        nearest.MarkerColor = Color.Red;
    } 

扩大 MarkerSize 当然也很简单(至少除非你的 ChartTypeBubble,就像我的一样 ;-)

  • 另一种解决方法会相当混乱:您可以添加一个额外的 ChartArea将其完全 覆盖在原始图表上。您必须获得原件的 ElementPositions 及其 InnerPlotPositionElementPositions,然后将它们用于叠加层。现在您可以将系列移动到第二个,上部 ChartArea 并关闭其 Axis 等。HitTest 现在应该可以按预期工作。但是每次调整大小都需要调整位置。