很久以前,我建立了一个跟踪类来管理一系列测量点:

public class TraceXYZ : CollectionBase, ICloneable { … }


后来,在我的软件中广泛使用TraceXYZ之后,我开始使用出色的图形软件包ZedGraph。因此,我添加了TraceXYZ方法.toLineItem(),该方法返回了与zedGraph GraphPane的CurveList属性兼容的LineItem

随着我越来越多地使用此功能,我发现在需要更新TraceXYZ对象并使修改后的值显示在zedGraph窗格中的应用程序中,它可能有些笨拙。由于目前存在,因此我必须在TraceXYZ中跟踪LineItem的关联CurveList,将其删除,然后创建并添加一个新的LineItem以反映修改后的TraceXYZ

允许CurveList直接在TraceXYZ上操作的功能是更可取的,但是由于我已经从CollectionBase继承,所以我也不能从LineItem继承。此外,在zedGraph中找不到任何关联的接口(例如ILineItem)可以使我实现该功能。

最后,我重新编码了TraceXYZ的内脏,以使用zedGraph PointPair对象的列表,然后尝试通过引用将它们复制到LineItem中,因此对TraceXYZ中原始点的修改将反映在zedGraph窗格中。但是,这没有用。显然,CurveList.AddPoint()方法执行点的克隆,并且不再引用TraceXYZ中的原始点。

所以…
有什么想法可以完成这样的事情吗?理想情况下,举例来说,我希望能够执行以下操作:

TraceXYZ trace = new TraceXYZ();

... populate trace points ...


pane.CurveList.Add( trace );
zedGraph.AxisChange( );
zedGraph.Refresh( );

trace[index].Y = aNewValue;

zedGraph.AxisChange( );
zedGraph.Refresh( );


并将新值Y反映在zedGraph窗格中。

(由于我广泛使用了TraceXYZ,因此对其进行了改造,使其继承自LineItem,这是一项重大而冒险的工作,但这只是不得已而为之。)

最佳答案

与其使TraceXYZ从LineItem派生,不如使用其他方法:

LineItem使用其Points属性与IPointList关联。每次在ZedGraph控件(或GraphPane对象)上调用Invalidate方法时,ZedGraph都会查询IPointList以获取要显示的整个列表点。

这是使ZedGraph独特的主要功能之一。

这意味着您可以使自定义集合类继承自IPointList并将其直接关联到您的LineItem。基本上,您将必须重写Count属性,返回PointPair对象的Indexer,可以被Clone欺骗的{ return this; }函数,就是这样。

不再需要填充点列表,ZedGraph将直接从您自己的集合中获取它。

例如,我设计了一个GenericPointList,它允许使用lambda选择器检索X和Y值,从而将几乎所有种类的列表投影为IPointList。因此,您可以看到实现自己的IPointList多么容易。

您可能只需要实现索引器:

public class TraceXYZ : CollectionBase, ICloneable, IPointList {
    public PointPair this[int index] {
        get {
            // return new PointPair(double X, double Y);
            return new PointPair(...
        }
    }

    public object Clone() {
        // Apparently, your objects implements ICloneable, so you likely implemented Clone already
    }

    public int Count {
        get {
            // Your objects implements CollectionBase, so Count is likely already implemented
        }
    }
}


在某些时候,您将拥有一些初始化代码:

TraceXYZ trace = new TraceXYZ();
...
var li = new LineItem(...
li.Points = TraceXYZ;
pane.CurveList.Add(li);


然后在某个时候:

trace[index].Y = aNewValue;
zedGraph.AxisChange( );
zedGraph.Refresh( );

10-06 07:14