Отвечая на этот вопрос проверки кода, я предложил решение с List<DataTable>
. Я пытаюсь инкапсулировать эту структуру данных в класс DataGridView Undo / Redo Manager. DataGridViewManager
и есть несколько встроенных методов, включая IsUndoable
, IsRedoable
, Push
, Redo
, Undo
и др. Реализованы следующие методы.
IsUndoable
обрабатывает процесс проверки доступности предыдущих состояний.IsRedoable
обрабатывает процесс проверки доступности следующих состояний.Push
обрабатывает процесс установки новых состояний.
Экспериментальная реализация
Экспериментальная реализация DataGridViewManager
как показано ниже.
using System;
using System.Data;
using System.Windows.Forms;
class DataGridViewManager
{
Stack<DataTable> dtStack = new Stack<DataTable>();
private int RecordIndex = 0;
public DataGridViewManager()
{ }
public DataGridViewManager Push(DataTable dataTable)
{
ClearUnnecessaryHistory();
this.dtStack.Push(dataTable);
return this;
}
public DataTable Redo()
{
return dtStack.ToList()[--RecordIndex];
}
public DataTable Undo()
{
return dtStack.ToList()[++RecordIndex];
}
public DataTable GetCurrentState()
{
return dtStack.ElementAt(RecordIndex);
}
public bool IsUndoable()
{
if (RecordIndex == this.dtStack.Count - 1)
return false;
else
return true;
}
public bool IsRedoable()
{
if (RecordIndex == 0)
return false;
else
return true;
}
private void ClearUnnecessaryHistory()
{
while (RecordIndex > 0)
{
dtStack.Pop();
RecordIndex--;
}
return;
}
}
Тестовые кейсы
Использование DataGridViewManager
класс похож на:
using System;
using System.Data;
using System.Windows.Forms;
public partial class Form1 : Form
{
DataGridViewManager DataGridViewManager1 = new DataGridViewManager();
public Form1()
{
InitializeComponent();
// Construct Columns
dataGridView1.ColumnCount = 1;
dataGridView1.Columns[0].Name = "0";
dataGridView1.Rows.Add(20);// Add row
DataGridViewManager1.Push(GetDataTableFromDGV(dataGridView1));
UpdateBtnStatus();
}
public DataTable GetDataTableFromDGV(DataGridView dgv)
{
var dt = new DataTable();
foreach (DataGridViewColumn column in dgv.Columns)
{
dt.Columns.Add(column.Name);
}
object[] cellValues = new object[dgv.Columns.Count];
foreach (DataGridViewRow row in dgv.Rows)
{
for (int i = 0; i < row.Cells.Count; i++)
{
cellValues[i] = row.Cells[i].Value;
}
dt.Rows.Add(cellValues);
}
return dt;
}
public void datatablaToDataGrid(DataGridView dgv, DataTable datatable)
{
for (int i = 0; i < datatable.Rows.Count; i++)
{
for (int j = 0; j < datatable.Columns.Count; j++)
{
dgv.Rows[i].Cells[j].Value = datatable.Rows[i][j].ToString();
}
}
}
private void UpdateBtnStatus()
{
btn_Redo.Enabled = DataGridViewManager1.IsRedoable();
btn_Undo.Enabled = DataGridViewManager1.IsUndoable();
return;
}
private void btn_Undo_Click(object sender, EventArgs e)
{
datatablaToDataGrid(dataGridView1, DataGridViewManager1.Undo());
UpdateBtnStatus();
}
private void btn_Redo_Click(object sender, EventArgs e)
{
datatablaToDataGrid(dataGridView1, DataGridViewManager1.Redo());
UpdateBtnStatus();
}
private void dataGridView1_CellValidated(object sender, DataGridViewCellEventArgs e)
{
UpdateBtnStatus();
DataGridView dgv = (DataGridView)sender;
int r = e.RowIndex;
int c = e.ColumnIndex;
if (dgv.Rows[r].Cells[c].Value != null)
{
string dgvResult = dgv.Rows[r].Cells[c].Value.ToString();
string dtResult = DataGridViewManager1.GetCurrentState().Rows[r][c].ToString();
if (dgvResult != dtResult)
{
DataGridViewManager1.Push(GetDataTableFromDGV(dataGridView1));
}
}
UpdateBtnStatus();
}
}
Все предложения приветствуются.