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

如何在Oxyplot Line Series中隐藏部分数据点且折线仍穿过隐藏点?

当然可行!我来教你怎么实现

完全可以做到你要的效果——隐藏部分数据点的标记,但折线依然穿过这些点,核心思路是保留所有数据点,只单独控制每个点的标记可见性,而不是删除数据点(删除的话折线就断了)。下面是具体的实现步骤:

1. 自定义带标记可见性属性的数据点类

OxyPlot原生的DataPoint没有标记可见性的属性,所以我们先扩展它,添加一个控制标记显示的字段,同时实现INotifyPropertyChanged以便动态更新:

public class CustomDataPoint : DataPoint, INotifyPropertyChanged
{
    private bool _isMarkerVisible = true;
    // 控制当前点的标记是否显示
    public bool IsMarkerVisible
    {
        get => _isMarkerVisible;
        set
        {
            if (_isMarkerVisible != value)
            {
                _isMarkerVisible = value;
                OnPropertyChanged(nameof(IsMarkerVisible));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    // 构造函数,兼容原生DataPoint的用法
    public CustomDataPoint(double x, double y) : base(x, y) { }
}

2. 自定义LineSeries重写标记渲染逻辑

接下来我们需要自定义一个LineSeries,重写它的标记渲染方法,在渲染时判断每个CustomDataPoint的IsMarkerVisible属性,只渲染需要显示的标记:

public class CustomLineSeries : LineSeries
{
    protected override void RenderMarkers(IRenderContext rc, IList<ScreenPoint> points)
    {
        // 如果没开标记显示、标记类型为None,直接返回
        if (MarkerType == MarkerType.None || !ShowMarkers)
            return;

        for (int i = 0; i < points.Count; i++)
        {
            // 只渲染IsMarkerVisible为true的点
            if (Items[i] is CustomDataPoint customPoint && !customPoint.IsMarkerVisible)
                continue;

            var screenPoint = points[i];
            rc.DrawMarker(
                screenPoint,
                MarkerType,
                MarkerOutline,
                MarkerFill,
                MarkerSize,
                MarkerStrokeThickness
            );
        }
    }
}

3. 使用自定义系列和数据点实现效果

现在就可以用这两个自定义类来创建图表了,示例代码如下:

// 创建PlotModel
var plotModel = new PlotModel { Title = "部分标记隐藏的折线图" };

// 创建自定义折线系列
var lineSeries = new CustomLineSeries
{
    MarkerType = MarkerType.Circle,
    MarkerSize = 6,
    MarkerFill = OxyColors.Blue,
    MarkerStroke = OxyColors.DarkBlue,
    ShowMarkers = true,
    StrokeThickness = 2
};

// 添加数据点,设置部分点隐藏标记
lineSeries.Items.Add(new CustomDataPoint(0, 2) { IsMarkerVisible = true });
lineSeries.Items.Add(new CustomDataPoint(1, 5) { IsMarkerVisible = false }); // 这个点标记隐藏,折线仍穿过
lineSeries.Items.Add(new CustomDataPoint(2, 3) { IsMarkerVisible = true });
lineSeries.Items.Add(new CustomDataPoint(3, 7) { IsMarkerVisible = false });
lineSeries.Items.Add(new CustomDataPoint(4, 4) { IsMarkerVisible = true });

plotModel.Series.Add(lineSeries);

// 把plotModel绑定到你的OxyPlot控件(比如WPF的PlotView)

4. 动态更新标记可见性

如果需要在运行时动态切换标记的显示/隐藏,只需要修改对应CustomDataPoint的IsMarkerVisible属性,然后调用plotModel.InvalidatePlot(true)刷新图表即可:

// 假设我们要隐藏第一个点的标记
var firstPoint = lineSeries.Items[0] as CustomDataPoint;
if (firstPoint != null)
{
    firstPoint.IsMarkerVisible = false;
    plotModel.InvalidatePlot(true);
}

关键注意事项

  • 不要直接移除DataPoint,否则折线会在该点位置断开,我们要做的只是隐藏标记,保留数据点本身。
  • 如果是WPF项目,在XAML中使用自定义CustomLineSeries时,记得添加对应的命名空间引用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:57:08