我想在 mschart 中看到剩余的行注释

I want to see remaining line annotation in mschart

在 mschart 中,我使用带有 SetAnchor 的线注释(第 8 点,第 12 点)。 如果我滚动图表并隐藏点 8,我将看不到剩余的线注释(点 9 到 12)。 我想查看剩余的行注释。帮帮我!

我的参考资料; Samples Environments for Microsoft Chart Controls --> 图表功能 --> 注释 --> 注释锚定

private void AddLineAnnotation()
{
    // create a line annotation
    LineAnnotation annotation = new LineAnnotation();

    // setup visual attributes
    annotation.StartCap = LineAnchorCapStyle.Arrow;
    annotation.EndCap = LineAnchorCapStyle.Arrow;
    annotation.LineWidth = 3;
    annotation.LineColor = Color.OrangeRed;
    annotation.ShadowOffset = 2;
    annotation.ClipToChartArea = "Default";

    // prevent moving or selecting
    annotation.AllowMoving = false;
    annotation.AllowAnchorMoving = false;
    annotation.AllowSelecting = false;

    if(Chart1.Series[0].Points.Count > 13)
    {
        // Use the Anchor Method to anchor to points 8 and 12...
        annotation.SetAnchor(Chart1.Series[0].Points[8], Chart1.Series[0].Points[12]);
    }

    // add the annotation to the collection
    Chart1.Annotations.Add(annotation);
}

这是一个棘手的问题。

坏消息是:我认为这是不可能的。我认为 MSChart 会忽略所有在可见区域之外开始的注释。也许推理是为了避免混乱,但谁知道..?

解决方法必须考虑到两个端点都在外面并且我们仍然希望看到注释的情况..

好消息是,使用 ownerdrawing 可以编写一种解决方法,确实可以为这两种情况划清界线。

下面的例子展示了绘图代码。确保将拖动以缩放和拖动以绘制新注释的模式分开。我使用复选框及其 CheckChanged 事件。

让我们先看看实际效果:

当注释的开头被滚动关闭时,线条图开始出现。很难注意到..

这是 xxxPaint 事件的代码:

private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
    // loop only over line annotations:
    List<LineAnnotation> annos =
        chart1.Annotations.Where(x => x is LineAnnotation)
                            .Cast<LineAnnotation>().ToList();
    if (!annos.Any()) return;

    // a few short references
    Graphics g = e.ChartGraphics.Graphics;
    ChartArea ca = chart1.ChartAreas[0];
    Axis ax = ca.AxisX;
    Axis ay = ca.AxisY;

    // we want to clip the line to the innerplotposition excluding the scrollbar:
    Rectangle r = Rectangle.Round(InnerPlotPositionClientRectangle(chart1, ca));
    g.SetClip(new Rectangle(r.X, r.Y, r.Width, r.Height - (int)ax.ScrollBar.Size));
    g.InterpolationMode = InterpolationMode.NearestNeighbor;  // pick your mode!
    foreach (LineAnnotation la in annos)
    {
        if (Double.IsNaN(la.Width)) continue;  // *
        // calculate the coordinates
        int x1 = (int)ax.ValueToPixelPosition(la.AnchorX);
        int y1 = (int)ay.ValueToPixelPosition(la.AnchorY);
        int x2 = (int)ax.ValueToPixelPosition(la.AnchorX + la.Width);
        int y2 = (int)ay.ValueToPixelPosition(la.AnchorY + la.Height);

        // now we draw the line if necessary:
        if (x1 < r.X || x1 > r.Right)
            using (Pen pen = new Pen(la.LineColor, 0.5f)) g.DrawLine(pen, x1, y1, x2, y2);
    }
    // reset the clip to allow the system drawing a scrollbar
    g.ResetClip();
}

一些注意事项:

  • 代码假定 (*) Annotations 全部锚定在 AnchorX/Y 上并且有一个 Width/Height 集合。如果您使用了不同的锚定方式,则需要调整代码。

  • 对于裁剪部分,我们需要知道 InnerPlotPosition 的像素 size/positon。为此,您可以使用例如中的代码在 .

  • 的底部
  • 除了一条直线,我什么都没写。如果您装饰了注释,则可能需要扩展代码;