很久以前,我建立了一个跟踪类来管理一系列测量点:
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( );