检测 DataGridViewCell 的 BackColor 变化
Detecting BackColor change of the DataGridViewCell
我正在开发一个 class,我们称它为 MyDataGridView,派生自必须与 Excel 文件同步的 DataGridView(即,当 DataGridView 中发生某些变化时,我需要对 Excel 文件进行相同的更改。
为了检测 DataGridView 中的变化,我使用事件(例如,RowsAdded、ColumnRemoved、CellValueChanged 等)。但是我在检测背景颜色已更改的单元格时遇到问题。
颜色被使用我的 class 的其他程序员更改。为此,他可以使用以下代码:
MyDataGridView myDataGridView;
// create and fill MyDataGridView...
myDataGridView.Rows[0].Cells[0].Style.BackColor = Color.AliceBlue;
我的目标是检测 BackColor 属性 的变化以更改 Excel 文件。
为了实现这个目标,我(未成功)尝试了几种方法:
CellStyleContentChanged 事件(问题:无法从事件处理程序中获取 Cell 本身)。
CellFormatting事件(问题:事件上升了很多次,我搞不懂它发生的原因)
CellStyleChanged 事件(问题:事件只发生在Style 属性改变时,而不是Style.BackColor)。
覆盖 DataGridViewCellStyle class(问题:我不知道如何正确覆盖这个 class 以及它是否可能)。
有助于重现我的尝试的代码片段:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
dataGridView1.CellStyleContentChanged += dataGridView1_CellStyleContentChanged;
dataGridView1.CellFormatting += dataGridView1_CellFormatting;
}
// Goal
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Columns.Add("column1", "column1");
dataGridView1.Columns.Add("column2", "column2");
dataGridView1.Rows.Add("cell1", "cell2");
// how to detect this?
dataGridView1.Rows[0].Cells[0].Style.BackColor = Color.AliceBlue;
}
// Attempt #1
void dataGridView1_CellStyleContentChanged(
object sender, DataGridViewCellStyleContentChangedEventArgs e)
{
// how to get cell itself (rowIndex & columnIndex)?
}
// Attempt #2
void dataGridView1_CellStyleChanged(object sender, DataGridViewCellEventArgs e)
{
// event only occurs when the Style property changes, but not Style.BackColor
}
// Attempt #3
void dataGridView1_CellFormatting(
object sender, DataGridViewCellFormattingEventArgs e)
{
// event rises so many times!
// and how to get reason of formatting (i need to detect only color change)?
}
// Attempt #4
// do i need something like this?
public class MyDataGridView : DataGridView
{
public class MyDataGridViewRowCollection : DataGridViewRowCollection
{
public MyDataGridViewRowCollection(DataGridView _dgv) : base(_dgv) { }
public class MyDataGridViewRow : DataGridViewRow
{
public class MyDataGridViewCellCollection : DataGridViewCellCollection
{
public MyDataGridViewCellCollection(DataGridViewRow _dgvRow) :
base(_dgvRow) { }
public class MyDataGridViewCell : DataGridViewCell
{
private new MyDataGridViewCellStyle Style { get; set; }
public class MyDataGridViewCellStyle : DataGridViewCellStyle
{
public new Color BackColor
{
get
{
return base.BackColor;
}
set
{
base.BackColor = value;
// TODO: changes in Excel
// ...
}
}
}
}
}
}
}
}
}
我很乐意接受任何建议和解答!
与@TaW 的讨论促使我同时使用多个事件。
我们使用 CellStyleContentChanged 事件来检测 Style.BackColor 变化,并使用 CellFormatting 事件来获取 Cell,其 BackColor 已被更改。
我们还需要一些 Collection 来存储更改的颜色,因为这些事件不会按顺序发生(请参阅下面的日志)。
备注!!此方法仅适用于用户可见的单元格(DataGridView 不应有滚动条)。
public partial class Form1 : Form
{
string log = "";
List<Color> changedBackColors = new List<Color>();
public Form1()
{
InitializeComponent();
this.dataGridView1.CellStyleContentChanged +=
dataGridView1_CellStyleContentChanged;
this.dataGridView1.CellFormatting +=
dataGridView1_CellFormatting;
this.Shown += Form1_Shown;
}
void Form1_Shown(object sender, EventArgs e)
{
log += "Change Cell[0,0] (color = blue)\r\n";
this.dataGridView1.Rows[0].Cells[0].Style.BackColor = Color.Blue;
log += "Change Cell[0,1] (color = red)\r\n";
this.dataGridView1.Rows[0].Cells[1].Style.BackColor = Color.Red;
}
private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.Columns.Add("column1", "column1");
this.dataGridView1.Columns.Add("column1", "column1");
this.dataGridView1.Rows.Add("cell1", "cell2");
}
private void dataGridView1_CellStyleContentChanged(
object sender, DataGridViewCellStyleContentChangedEventArgs e)
{
log += string.Format(
"CellStyleContentChanged occurs for Cell[?,?] (color = {0})\r\n",
e.CellStyle.BackColor.Name);
this.changedBackColors.Add(e.CellStyle.BackColor);
}
private void dataGridView1_CellFormatting(
object sender, DataGridViewCellFormattingEventArgs e)
{
if (this.changedBackColors.Count > 0)
{
if (this.changedBackColors.Contains(e.CellStyle.BackColor))
{
log += string.Format(
"CellFormatting occurs for Cell[{0},{1}] (color = {2})\r\n",
e.RowIndex, e.ColumnIndex, e.CellStyle.BackColor.Name);
this.changedBackColors.Remove(e.CellStyle.BackColor);
// TODO: change excel file
// ...
}
}
}
}
日志:
- 更改单元格[0,0](颜色=蓝色)
- 单元格发生 CellStyleContentChanged[?,?](颜色 = 蓝色)
- 更改单元格[0,1](颜色=红色)
- 单元格发生 CellStyleContentChanged[?,?](颜色 = 红色)
- Cell[0,0] 出现 CellFormatting(颜色 = 蓝色)
- 单元格 [0,1](颜色 = 红色)发生单元格格式化
我正在开发一个 class,我们称它为 MyDataGridView,派生自必须与 Excel 文件同步的 DataGridView(即,当 DataGridView 中发生某些变化时,我需要对 Excel 文件进行相同的更改。
为了检测 DataGridView 中的变化,我使用事件(例如,RowsAdded、ColumnRemoved、CellValueChanged 等)。但是我在检测背景颜色已更改的单元格时遇到问题。
颜色被使用我的 class 的其他程序员更改。为此,他可以使用以下代码:
MyDataGridView myDataGridView;
// create and fill MyDataGridView...
myDataGridView.Rows[0].Cells[0].Style.BackColor = Color.AliceBlue;
我的目标是检测 BackColor 属性 的变化以更改 Excel 文件。
为了实现这个目标,我(未成功)尝试了几种方法:
CellStyleContentChanged 事件(问题:无法从事件处理程序中获取 Cell 本身)。
CellFormatting事件(问题:事件上升了很多次,我搞不懂它发生的原因)
CellStyleChanged 事件(问题:事件只发生在Style 属性改变时,而不是Style.BackColor)。
覆盖 DataGridViewCellStyle class(问题:我不知道如何正确覆盖这个 class 以及它是否可能)。
有助于重现我的尝试的代码片段:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
dataGridView1.CellStyleContentChanged += dataGridView1_CellStyleContentChanged;
dataGridView1.CellFormatting += dataGridView1_CellFormatting;
}
// Goal
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.Columns.Add("column1", "column1");
dataGridView1.Columns.Add("column2", "column2");
dataGridView1.Rows.Add("cell1", "cell2");
// how to detect this?
dataGridView1.Rows[0].Cells[0].Style.BackColor = Color.AliceBlue;
}
// Attempt #1
void dataGridView1_CellStyleContentChanged(
object sender, DataGridViewCellStyleContentChangedEventArgs e)
{
// how to get cell itself (rowIndex & columnIndex)?
}
// Attempt #2
void dataGridView1_CellStyleChanged(object sender, DataGridViewCellEventArgs e)
{
// event only occurs when the Style property changes, but not Style.BackColor
}
// Attempt #3
void dataGridView1_CellFormatting(
object sender, DataGridViewCellFormattingEventArgs e)
{
// event rises so many times!
// and how to get reason of formatting (i need to detect only color change)?
}
// Attempt #4
// do i need something like this?
public class MyDataGridView : DataGridView
{
public class MyDataGridViewRowCollection : DataGridViewRowCollection
{
public MyDataGridViewRowCollection(DataGridView _dgv) : base(_dgv) { }
public class MyDataGridViewRow : DataGridViewRow
{
public class MyDataGridViewCellCollection : DataGridViewCellCollection
{
public MyDataGridViewCellCollection(DataGridViewRow _dgvRow) :
base(_dgvRow) { }
public class MyDataGridViewCell : DataGridViewCell
{
private new MyDataGridViewCellStyle Style { get; set; }
public class MyDataGridViewCellStyle : DataGridViewCellStyle
{
public new Color BackColor
{
get
{
return base.BackColor;
}
set
{
base.BackColor = value;
// TODO: changes in Excel
// ...
}
}
}
}
}
}
}
}
}
我很乐意接受任何建议和解答!
与@TaW 的讨论促使我同时使用多个事件。
我们使用 CellStyleContentChanged 事件来检测 Style.BackColor 变化,并使用 CellFormatting 事件来获取 Cell,其 BackColor 已被更改。
我们还需要一些 Collection 来存储更改的颜色,因为这些事件不会按顺序发生(请参阅下面的日志)。
备注!!此方法仅适用于用户可见的单元格(DataGridView 不应有滚动条)。
public partial class Form1 : Form
{
string log = "";
List<Color> changedBackColors = new List<Color>();
public Form1()
{
InitializeComponent();
this.dataGridView1.CellStyleContentChanged +=
dataGridView1_CellStyleContentChanged;
this.dataGridView1.CellFormatting +=
dataGridView1_CellFormatting;
this.Shown += Form1_Shown;
}
void Form1_Shown(object sender, EventArgs e)
{
log += "Change Cell[0,0] (color = blue)\r\n";
this.dataGridView1.Rows[0].Cells[0].Style.BackColor = Color.Blue;
log += "Change Cell[0,1] (color = red)\r\n";
this.dataGridView1.Rows[0].Cells[1].Style.BackColor = Color.Red;
}
private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.Columns.Add("column1", "column1");
this.dataGridView1.Columns.Add("column1", "column1");
this.dataGridView1.Rows.Add("cell1", "cell2");
}
private void dataGridView1_CellStyleContentChanged(
object sender, DataGridViewCellStyleContentChangedEventArgs e)
{
log += string.Format(
"CellStyleContentChanged occurs for Cell[?,?] (color = {0})\r\n",
e.CellStyle.BackColor.Name);
this.changedBackColors.Add(e.CellStyle.BackColor);
}
private void dataGridView1_CellFormatting(
object sender, DataGridViewCellFormattingEventArgs e)
{
if (this.changedBackColors.Count > 0)
{
if (this.changedBackColors.Contains(e.CellStyle.BackColor))
{
log += string.Format(
"CellFormatting occurs for Cell[{0},{1}] (color = {2})\r\n",
e.RowIndex, e.ColumnIndex, e.CellStyle.BackColor.Name);
this.changedBackColors.Remove(e.CellStyle.BackColor);
// TODO: change excel file
// ...
}
}
}
}
日志:
- 更改单元格[0,0](颜色=蓝色)
- 单元格发生 CellStyleContentChanged[?,?](颜色 = 蓝色)
- 更改单元格[0,1](颜色=红色)
- 单元格发生 CellStyleContentChanged[?,?](颜色 = 红色)
- Cell[0,0] 出现 CellFormatting(颜色 = 蓝色)
- 单元格 [0,1](颜色 = 红色)发生单元格格式化