You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#时间轴图表中绘制垂直线并避免重复生成

C# Chart控件避免重复生成当前时间垂直线的解决方法

问题描述

我使用C# Chart控件展示每日潮汐随时间变化的数据,希望用垂直线标记当前时间。现有代码可实现该功能,但将VerticalLine()绑定到定时器后,随着时间推移会生成多条垂直线,请问如何避免这种情况?

原有实现代码:

private void VerticalLine()
{    
    double MyDate = DateTime.Now.ToOADate();

    double maxDataPoint = chart.ChartAreas[0].AxisY.Maximum;
    double minDataPoint = chart.ChartAreas[0].AxisY.Minimum;

    LineAnnotation annotation = new LineAnnotation();
    annotation.IsSizeAlwaysRelative = false;
    annotation.AxisX = chart.ChartAreas[0].AxisX;
    annotation.AxisY = chart.ChartAreas[0].AxisY;
    annotation.AnchorY = minDataPoint;
    annotation.Height = maxDataPoint - minDataPoint;;
    annotation.Width = 0;
    annotation.LineWidth = 1;
    annotation.StartCap = LineAnchorCapStyle.None;
    annotation.EndCap = LineAnchorCapStyle.None;
    annotation.AnchorX = MyDate;  // <- your point
    annotation.LineColor = Color.Red; // <- your color
    chart.Annotations.Add(annotation);
}

private void timer_Tick(object sender, EventArgs e)
{
    VerticalLine();
}

问题根源:每次定时器触发都会创建新的LineAnnotation实例并添加到chart.Annotations集合中,导致垂直线不断累积。


解决方案

方法一:复用同一个LineAnnotation对象

将LineAnnotation声明为类级别的成员变量,仅在首次调用时创建,后续触发定时器时只更新其位置和属性,避免重复创建对象。

修改后的代码:

// 声明为类成员变量,确保全局唯一
private LineAnnotation _currentTimeLine;

private void VerticalLine()
{    
    double myDate = DateTime.Now.ToOADate();
    double maxDataPoint = chart.ChartAreas[0].AxisY.Maximum;
    double minDataPoint = chart.ChartAreas[0].AxisY.Minimum;

    // 仅在首次调用时创建注释对象
    if (_currentTimeLine == null)
    {
        _currentTimeLine = new LineAnnotation();
        _currentTimeLine.IsSizeAlwaysRelative = false;
        _currentTimeLine.AxisX = chart.ChartAreas[0].AxisX;
        _currentTimeLine.AxisY = chart.ChartAreas[0].AxisY;
        _currentTimeLine.LineWidth = 1;
        _currentTimeLine.StartCap = LineAnchorCapStyle.None;
        _currentTimeLine.EndCap = LineAnchorCapStyle.None;
        _currentTimeLine.LineColor = Color.Red;
        chart.Annotations.Add(_currentTimeLine);
    }

    // 更新垂直线的位置和高度(适配Y轴范围变化)
    _currentTimeLine.AnchorY = minDataPoint;
    _currentTimeLine.Height = maxDataPoint - minDataPoint;
    _currentTimeLine.Width = 0;
    _currentTimeLine.AnchorX = myDate;
}

private void timer_Tick(object sender, EventArgs e)
{
    VerticalLine();
}

方法二:每次更新前移除旧的垂直线

在创建新的垂直线之前,先从chart.Annotations集合中移除之前的时间标记线。可以通过名称标记或属性筛选来精准定位要移除的注释。

方式1:通过名称标记筛选

private void VerticalLine()
{    
    // 移除已有的时间标记线(通过名称精准匹配)
    var existingLine = chart.Annotations["CurrentTimeLine"];
    if (existingLine != null)
    {
        chart.Annotations.Remove(existingLine);
    }

    double myDate = DateTime.Now.ToOADate();
    double maxDataPoint = chart.ChartAreas[0].AxisY.Maximum;
    double minDataPoint = chart.ChartAreas[0].AxisY.Minimum;

    LineAnnotation annotation = new LineAnnotation();
    annotation.Name = "CurrentTimeLine"; // 设置唯一名称,方便后续查找
    annotation.IsSizeAlwaysRelative = false;
    annotation.AxisX = chart.ChartAreas[0].AxisX;
    annotation.AxisY = chart.ChartAreas[0].AxisY;
    annotation.AnchorY = minDataPoint;
    annotation.Height = maxDataPoint - minDataPoint;
    annotation.Width = 0;
    annotation.LineWidth = 1;
    annotation.StartCap = LineAnchorCapStyle.None;
    annotation.EndCap = LineAnchorCapStyle.None;
    annotation.AnchorX = myDate;
    annotation.LineColor = Color.Red;
    chart.Annotations.Add(annotation);
}

private void timer_Tick(object sender, EventArgs e)
{
    VerticalLine();
}

方式2:通过属性筛选

如果没有设置名称,也可以通过注释类型和颜色等属性筛选:

private void VerticalLine()
{    
    // 移除已有的红色垂直线注释
    var existingLine = chart.Annotations.OfType<LineAnnotation>()
                                        .FirstOrDefault(a => a.LineColor == Color.Red);
    if (existingLine != null)
    {
        chart.Annotations.Remove(existingLine);
    }

    // 后续创建新注释的代码和原有逻辑一致
    double myDate = DateTime.Now.ToOADate();
    double maxDataPoint = chart.ChartAreas[0].AxisY.Maximum;
    double minDataPoint = chart.ChartAreas[0].AxisY.Minimum;

    LineAnnotation annotation = new LineAnnotation();
    annotation.IsSizeAlwaysRelative = false;
    annotation.AxisX = chart.ChartAreas[0].AxisX;
    annotation.AxisY = chart.ChartAreas[0].AxisY;
    annotation.AnchorY = minDataPoint;
    annotation.Height = maxDataPoint - minDataPoint;
    annotation.Width = 0;
    annotation.LineWidth = 1;
    annotation.StartCap = LineAnchorCapStyle.None;
    annotation.EndCap = LineAnchorCapStyle.None;
    annotation.AnchorX = myDate;
    annotation.LineColor = Color.Red;
    chart.Annotations.Add(annotation);
}

private void timer_Tick(object sender, EventArgs e)
{
    VerticalLine();
}

内容的提问来源于stack exchange,提问作者Ulrich Rosin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:00:05