在 DoubleClick 上交换 DataGridViewImageColumn 的图像和工具提示

问题描述 投票:0回答:1

我在 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;
                }
            }
        }
    }
c# winforms datagridview
1个回答
0
投票

注意:

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 的 Value 是否为 null 或 DbNull.Value。没关系,如果数据不是来自数据库,安全总比后悔好

当您更改了受影响的 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();
}
© www.soinside.com 2019 - 2024. All rights reserved.