在m_gridView_ValidatingEditor中得到cell修改之前的值,然后保存起来。
private void m_toolUndo_Click(object sender, EventArgs e)
{
if (m_undoInfo.Available)
{
DataTable dt = m_gridControl.DataSource as DataTable;
dt.AcceptChanges();
ActionData actionData = m_undoInfo.Pop();
CellActionData cellActionData = actionData as CellActionData;
if (cellActionData != null)
{
switch (cellActionData.ActionType)
{
case EnuActionType.ChangeCell:
foreach (CellActionDataItem dataItem in cellActionData.DataItemList)
{
DataRow[] rows = dt.Select("AutoGen=" + dataItem.AutoGenId);
if (rows.Length > 0)
{
rows[0][dataItem.ColumnName] = dataItem.OrgValue;
}
}
break;
case EnuActionType.AddRow:
foreach (CellActionDataItem dataItem in cellActionData.DataItemList)
{
DataRow[] rows = dt.Select("AutoGen=" + dataItem.AutoGenId);
if (rows.Length > 0)
{
dt.Rows.Remove(rows[0]);
}
}
break;
case EnuActionType.DeleteRow:
foreach (CellActionDataItem dataItem in cellActionData.DataItemList)
{
DataRow[] rows = dt.Select("AutoGen=" + dataItem.AutoGenId);
if (rows.Length > 0)
{
rows[0][dataItem.ColumnName] = dataItem.OrgValue;
}
else
{
DataRow drNew = dt.NewRow();
drNew[dataItem.ColumnName] = dataItem.OrgValue;
dt.Rows.Add(drNew);
}
}
break;
}
}
else
{
ColumnActionData columnActionData = actionData as ColumnActionData;
if (columnActionData != null)
{
int idxOrdinal = dt.Columns.IndexOf(columnActionData.ColumnName);
foreach (ColumnActionDataItem dataItem in columnActionData.DataItemList)
{
DataRow[] rows = dt.Select("AutoGen=" + dataItem.AutoGenId);
if (rows.Length > 0)
{
rows[0][idxOrdinal] = dataItem.OrgValue;
}
}
}
}
dt.AcceptChanges();
}
else
{
MsgHelper.Alert("No undo info");
}
}
private void m_gridView_ValidatingEditor(object sender, DevExpress.XtraEditors.Controls.BaseContainerValidateEditorEventArgs e)
{
CellActionData cellActionData = new CellActionData(EnuActionType.ChangeCell);
DataRow dr = m_gridView.GetDataRow(m_gridView.FocusedRowHandle);
cellActionData.DataItemList.Add(new CellActionDataItem(m_gridView.FocusedColumn.FieldName, Convert.ToInt32(dr["AutoGen"]), dr[m_gridView.FocusedColumn.FieldName]));
m_undoInfo.Push(cellActionData);
}
private void m_gridControl_EmbeddedNavigator_ButtonClick(object sender, DevExpress.XtraEditors.NavigatorButtonClickEventArgs e)
{
if (e.Button.ButtonType == DevExpress.XtraEditors.NavigatorButtonType.Append)
{
m_gridView.PostEditor();
m_gridView.UpdateCurrentRow();
DataTable dt = m_gridControl.DataSource as DataTable;
if (dt != null)
{
dt.AcceptChanges();
FrmSelectFileIdAndSheetName frm = new FrmSelectFileIdAndSheetName(dt);
frm.OnOK += new EventHandler<SelectFileIdAndSheetNameArgs>(frm_OnOK);
frm.ShowDialog();
}
e.Handled = true;
}
else if (e.Button.ButtonType == DevExpress.XtraEditors.NavigatorButtonType.Remove)
{
int[] arrRowHandle = m_gridView.GetSelectedRows();
CellActionData cellActionData = new CellActionData(EnuActionType.DeleteRow);
foreach(int rowHandle in arrRowHandle)
{
DataRow dr = m_gridView.GetDataRow(rowHandle);
foreach (DataColumn dataCol in dr.Table.Columns)
{
cellActionData.DataItemList.Add(new CellActionDataItem(dataCol.ColumnName, Convert.ToInt32(dr["AutoGen"]), dr[dataCol]));
}
}
m_undoInfo.Push(cellActionData);
}
}
private void frm_OnOK(object sender, SelectFileIdAndSheetNameArgs e)
{
DataTable dt = m_gridControl.DataSource as DataTable;
DataRow dr = dt.NewRow();
dr[m_colOriginalFileId.FieldName] = e.FileId;
dr[m_colSheetName.FieldName] = e.SheetName;
CellActionData cellActionData = new CellActionData(EnuActionType.AddRow);
cellActionData.DataItemList.Add(new CellActionDataItem("AutoGen", Convert.ToInt32(dr["AutoGen"]), dr["AutoGen"]));
m_undoInfo.Push(cellActionData);
dt.Rows.Add(dr);
}
-----------------------------------------
class UndoInfo
{
private LinkedList<ActionData> m_UndoList = new LinkedList<ActionData>();
private int m_capacity = 10;
public event EventHandler ChangedHandler = null;
public void PushColumn(EnuActionType enActionType, DataTable dt, string columnName)
{
if (dt == null || dt.Rows.Count == 0)
{
return;
}
int idxOrdinal = dt.Columns.IndexOf(columnName);
ColumnActionData columnActionData = new ColumnActionData(enActionType, columnName);
foreach (DataRow dr in dt.Rows)
{
columnActionData.DataItemList.Add(new ColumnActionDataItem(Convert.ToInt32(dr["AutoGen"]), dr[idxOrdinal]));
}
Push(columnActionData);
}
public void Push(ActionData curVal)
{
if (curVal == null)
{
return;
}
CellActionData cellActionData = curVal as CellActionData;
if (cellActionData != null)
{
if (cellActionData.DataItemList.Count == 0)
{
return;
}
}
else
{
ColumnActionData columnActionData = curVal as ColumnActionData;
if (columnActionData != null)
{
if (columnActionData.DataItemList.Count == 0)
{
return;
}
}
else
{
throw new NotImplementedException("Not implemented.");
}
}
m_UndoList.AddLast(curVal);
while (m_UndoList.Count > m_capacity)
{
m_UndoList.RemoveFirst();
}
Notify();
}
public int Count
{
get
{
return m_UndoList.Count;
}
}
public bool Available
{
get
{
return (m_UndoList.Count > 0);
}
}
public ActionData Pop()
{
if (Available)
{
ActionData tmp = m_UndoList.Last.Value;
m_UndoList.RemoveLast();
Notify();
return tmp;
}
else
{
throw new InvalidOperationException("Undo list is empty.");
}
}
public void Clear()
{
m_UndoList.Clear();
Notify();
}
private void Notify()
{
if (ChangedHandler != null)
{
ChangedHandler(null, null);
}
}
}
enum EnuActionType
{
ChangeCell,
AddRow,
DeleteRow,
}
class ActionData
{
public ActionData(EnuActionType enActionType)
{
ActionType = enActionType;
}
public readonly EnuActionType ActionType;
}
class CellActionData : ActionData
{
public CellActionData(EnuActionType enActionType)
: base(enActionType)
{
DataItemList = new List<CellActionDataItem>();
}
public readonly List<CellActionDataItem> DataItemList;
}
class ColumnActionData : ActionData
{
public ColumnActionData(EnuActionType enActionType, string strColumnName)
: base(enActionType)
{
ColumnName = strColumnName;
DataItemList = new List<ColumnActionDataItem>();
}
public readonly string ColumnName;
public readonly List<ColumnActionDataItem> DataItemList;
}
class CellActionDataItem
{
public string ColumnName;
public int AutoGenId;
public object OrgValue;
public CellActionDataItem(string strColumnName, int genId, object val)
{
ColumnName = strColumnName;
AutoGenId = genId;
OrgValue = val;
}
}
class ColumnActionDataItem
{
public int AutoGenId;
public object OrgValue;
public ColumnActionDataItem(int genId, object val)
{
AutoGenId = genId;
OrgValue = val;
}
}
==================================
当仅仅只是粗略的整个状态进行保存用如下代码:
class UndoInfo
{
private LinkedList<DataTable> m_UndoList = new LinkedList<DataTable>();
private int m_capacity = 1;
public event EventHandler ChangedHandler = null;
public void Push(DataTable curVal)
{
DataTable objNew = null;
if (curVal != null)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, curVal);
stream.Flush();
stream.Position = 0;
objNew = formatter.Deserialize(stream) as DataTable;
}
}
m_UndoList.AddLast(objNew);
while (m_UndoList.Count > m_capacity)
{
m_UndoList.RemoveFirst();
}
Notify();
}
public bool Available
{
get
{
return (m_UndoList.Count > 0);
}
}
public DataTable Pop()
{
if (Available)
{
DataTable tmp = m_UndoList.Last.Value;
m_UndoList.RemoveLast();
Notify();
return tmp;
}
else
{
throw new InvalidOperationException("Undo list is empty.");
}
}
public void Clear()
{
m_UndoList.Clear();
Notify();
}
private void Notify()
{
if (ChangedHandler == null)
{
ChangedHandler(null, null);
}
}
}