撤消图表中系列的操作

Undo operation for series in chart

我想在图表中多次更改一些 Yvalues[0] 后恢复以前的系列。所以我已经使用备忘录模式实现了撤消操作。

但是在 运行 时它不工作并且没有错误。下面是发起人、纪念品和看守人。

public class Originator
{

    private Series _series = new Series();

    public Originator(Series series)
    {
        _series = series;
    }
    public Series OSeries
    {
        get
        {
            return _series;
        }
        set
        {
            _series = value;
        }
    }

    public Memento SaveSeries()
    {
        return new Memento(_series);
    }

    public void RestoreSeries(Memento m)
    {
        this._series = m.MMseries;
    }
 }

public class Memento
{
    private Series _series =new Series();

    public Memento(Originator org)
    {
        this._series = org.OSeries;
    }
    public Memento(Series mseries)
    {
        _series = mseries;
    }

    public Series MMseries
    {
        get
        {
            return _series;
        }
        set
        {
            _series = value;
        }
    }
}
public class Caretaker
{
    //  private static Caretaker _instance;


    //  public Caretaker() { }

    private Memento chartMemento;
    public Memento Memento
    {
        get
        { return chartMemento; }

        set
        {  chartMemento = value; }

    }
}

在 public 部分 class Form1 中创建对象:Form

Originator _org;
Caretaker taker = new Caretaker();

从文件加载图表时,open_file 函数包含此代码:

_org = new Originator(global_series); //For undo/redo operation
while (chart1.Series.Count > 0) { chart1.Series.RemoveAt(0); }

chart1.Series.Add(global_series);
taker.Memento = _org.SaveSeries();

对于Undo_button:

_org.RestoreSeries(taker.Memento);
while (chart1.Series.Count > 0) { chart1.Series.RemoveAt(0); }
global_series = _org.OSeries;
chart1.Series.Add(global_series);

Series 是一个 reference 变量。

因此,您所做的所有更改都将针对该系列,并且您拥有的所有参考文献都将指向同一个(原始)系列。

花哨的模式,虽然它们可能很有用,但不能替代基础知识。要允许 undo/redo,您需要 datacopy,而不是 参考!

请注意 Series 没有 Clone 方法。

所以你需要自己动手;在您的情况下,这归结为 复制点数..

但对于更一般的情况,您可能希望复制其他系列属性,最著名的是 ChartType,但基本上您为准备 Series 所做的一切。也许以工厂模式创建它..?

但是 还要注意 DataPoint 有一个 Clone 方法。因此,您可以像这样更改 Originator 构造函数:

public Originator(Series series)
{
    //_series = series;
    foreach (var dp in series.Points) _series.Points.Add(dp.Clone());
}

一切都会按预期开始工作。但是你也需要像这样进行恢复,否则你会指向保存的系列,接下来的更改会改变它而不是图表系列。:

public void RestoreSeries(Memento m)
{
    // this._series = m.MMseries;
    this._series.Points.Clear();
    foreach (var dp in m.MMseries.Points) this._series.Points.Add(dp);
}

顺便说一句:要清除所有系列,请使用 chart.Series.Clear() !

使用 Memento Pattern 进行多次撤消操作

管理员代码:

public class Caretaker
{

    private Memento chartMemento;
    public Memento Memento
    {
        get
        { return chartMemento; }

        set
        {  chartMemento = value; }

    }
}

纪念品代码:

public class Memento
{
    private Series _series =new Series();

    public Memento(Originator org)
    {
        this._series.Points.Clear();
        foreach (var dp in org.OSeries.Points) this._series.Points.Add(dp.Clone());
    }
    public Memento(Series mseries)
    {
        this._series.Points.Clear();
        foreach (var dp in mseries.Points) this._series.Points.Add(dp.Clone());
    }

    public Series MMseries
    {
        get
        {
            return _series;
        }
        set
        {
            _series = value;
        }
    }
}

创始人代码

public class Originator{
    private Series _series = new Series();
    public Originator() { }
    public Originator(Series series)
    {
        // _series = series;
        _series.Points.Clear();
        foreach (var dp in series.Points) _series.Points.Add(dp.Clone());
    }
    public Series OSeries
    {
        get
        {
            return _series;
        }
        set
        {
            _series = value;
        }
    }

    public Memento SaveSeries()
    {
        return new Memento(_series);
    }

    public void RestoreSeries(Memento m)
    {
        //this._series = m.MMseries;

        this._series.Points.Clear();
        foreach (var dp in m.MMseries.Points) this._series.Points.Add(dp);
        this._series.ChartType = SeriesChartType.Line;
    }

}

在 Form1 中声明对象列表及其计数器

 Orginator _org;
 List<Originator> list_org = new List<Originator>();
 List<Caretaker> list_taker = new List<Caretaker>();
 int obj_counter = 0;

Do 操作代码

 list_org.Add(_org = new Originator(global_series));
 Caretaker ct = new Caretaker();
 ct.Memento = list_org[obj_counter++].SaveSeries();
 list_taker.Add(ct);

撤消操作代码:

  if (obj_counter > 0)
  {
     list_org[--obj_counter].RestoreSeries(list_taker[obj_counter].Memento);
     global_series.Points.Clear();
     foreach (var dp in list_org[obj_counter].OSeries.Points) 
     global_series.Points.Add(dp);
  }