如何在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
相关产品推荐
相关产品推荐

