我在 C# WinForms 应用程序中使用 DataGridView 来显示关联数据库中的锁(由用户、应用程序分配)。用户会看到当前锁的列表,显示相关信息,最后一个可见列是 DataGridViewImageColumn,其中图像来自应用程序资源。
最后还有一个隐藏的 DataGridViewCheckBoxColumn,当用户双击某行的图标时会选中该列,如果用户双击该行的同一图标(即重置其选择)则取消选中该列。
我想做的是,根据复选框的值,交换 CellContentDoubleClick 事件中的图像和工具提示,如下所示,但我没有看到图标或工具提示的更改。 “ProjectLocked”是 DataGridViewImageColumn 的名称,“DeleteLock”是 DataGridViewCheckBoxColumn 的名称。
private void dgvProjectLocks_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
{
// do nothing for the header row
if (e.RowIndex < 0) return;
// caste the object to the correct type
var dgv = (DataGridView)sender;
// Do nothing if the clicked column is not the ProjectLocked column
if (dgv.Columns[e.ColumnIndex].Name != "ProjectLocked") return;
// Get the clicked row
using (var currentRow = dgv.Rows[e.RowIndex])
{
using (var deleteCell = currentRow.Cells["DeleteLock"])
{
switch (Convert.ToBoolean(deleteCell.Value))
{
case true:
currentRow.DefaultCellStyle.BackColor = dgv.DefaultCellStyle.BackColor;
currentRow.DefaultCellStyle.ForeColor = dgv.DefaultCellStyle.ForeColor;
deleteCell.Value = false;
currentRow.Cells["ProjectLocked"].Value = Resources.locked;
deleteCell.ToolTipText = Resources.AddProjectLockDeleteToolTip;
break;
case false:
currentRow.DefaultCellStyle.BackColor = Color.LightGray;
currentRow.DefaultCellStyle.ForeColor = Color.DarkGray;
deleteCell.Value = true;
currentRow.Cells["ProjectLocked"].Value = Resources.unlocked;
deleteCell.ToolTipText = Resources.RemoveProjectLockDeleteToolTip;
break;
}
}
}
}
注意:
Properties.Resources
是一个工厂,每次请求时它都会返回一个新对象。当您从资源中分配一个新对象时,它所替换的对象将留给 GC。对于 Graphics 对象来说,这不是一件好事。更好地缓存这些对象并使用缓存的值。Dictionary<bool, Image>
作为存储设施:
private Dictionary<bool, Image> DataGridViewLockState = new Dictionary<bool, Image>() {
[true] = Resources.locked,
[false] = Resources.unlocked
};
关于此处提供的代码:
using
语句来声明它。您需要引用的对象处于活动状态,在这里,这些是您的行/单元格其他:
e.RowIndex
和 e.ColumIndex
是否为负值,因为在某些时候两者都可能为负值(您可能禁用了列排序,没关系,这是程序)当您更改了受影响的 Cell 的当前状态时,请调用
[DataGridView].EndEdit()
方法。这会立即提交更改。CellValueChanged
事件。如果您在该事件处理程序中有代码,请记住这一点。EndEdit()
,以避免某种形式的 重新进入
private void dgvTest_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e) {
var dgv = sender as DataGridView;
if (dgv is null || e.RowIndex < 0 || e.ColumnIndex < 0) return;
if (dgv.Columns[e.ColumnIndex].Name != "ProjectLocked") return;
var currentRow = dgv.Rows[e.RowIndex];
var deleteCell = currentRow.Cells["DeleteLock"];
if (deleteCell.Value is null || deleteCell.Value == DBNull.Value) {
throw new InvalidOperationException("DeleteLock value cannot be null");
}
// Negate the current value, we want to change state
bool value = !(bool)deleteCell.Value;
currentRow.Cells["ProjectLocked"].Value = DataGridViewLockState[value];
currentRow.Cells["ProjectLocked"].ToolTipText = value ? Resources.RowLocked : Resources.RowUnlocked;
currentRow.DefaultCellStyle.BackColor = value ? dgv.DefaultCellStyle.BackColor : Color.LightGray;
currentRow.DefaultCellStyle.ForeColor = value ? dgv.DefaultCellStyle.ForeColor : Color.DarkGray;
deleteCell.Value = value;
dgv.EndEdit();
}