【问题标题】:DataGridViewComboBoxColumn Event Fire too many timesDataGridViewComboBoxColumn 事件触发太多次
【发布时间】:2020-10-15 21:06:01
【问题描述】:

在下拉组合中选择一个值后,我在停止第二次触发事件时遇到问题。该事件会打开一个对话框,告诉用户是否要使用是或否选项保存它。

我有一个网格视图,上面有 2 列:

我的代码如下。

namespace WindowsFormsApp3
{
    public partial class Form1 : Form
    {
        List<Team> teamList = new List<Team>();
        List<Team_Colour> teamColourList = new List<Team_Colour>();
        DataGridViewComboBoxColumn cb = new DataGridViewComboBoxColumn();
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            teamList.Add(new Team { name = "Test A", Colour_ID = 1});
            teamList.Add(new Team { name = "Test B", Colour_ID = 2 });
            teamList.Add(new Team { name = "Test C", Colour_ID = 3 });
            teamList.Add(new Team { name = "Test D", Colour_ID = 4 });

            dataGridView1.DataSource = teamList;
            dataGridView1.Columns[1].Visible = false;
            cb.HeaderText = "Colour";

            teamColourList.Add(new Team_Colour { Colour_ID = 1, Colour_Name = "None" });
            teamColourList.Add(new Team_Colour { Colour_ID = 2, Colour_Name = "Green" });
            teamColourList.Add(new Team_Colour { Colour_ID = 3, Colour_Name = "Blue" });
            teamColourList.Add(new Team_Colour { Colour_ID = 4, Colour_Name = "Red" });


            cb.DataSource = teamColourList;
            cb.DisplayMember = "Colour_Name";
            cb.ValueMember = "Colour_ID";
            cb.DataPropertyName = "Colour_ID";


            dataGridView1.Columns.Insert(1, cb);

        }

        private void DataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            DialogResult dialogResult = MessageBox.Show("Are you sure", "Saving", MessageBoxButtons.YesNo);
            if (dialogResult == DialogResult.Yes)
            {
                
            }
            else if (dialogResult == DialogResult.No)
            {
                
            }
        }
    }
}

当我单击第一行下拉列表中的新值时,事件按预期触发:

当我单击“是”时,对话框消失,但下拉菜单看起来仍像被选中,因为它看起来与其他选项不同:

一旦我尝试选择另一个下拉菜单的箭头,它就会再次被触发,就像它没有被聚焦一样。

如果在第一个对话框中单击“是”后被聚焦,如何停止?

【问题讨论】:

  • 我不会否认事件触发了两次。当用户“点击一个单元格”和用户“离开一个单元格”时,它会触发“一次”。这可能是CurrentCellDirtyStateChanged 事件的本质,但是,我不得不问……你确定这是你想用来“保存”数据的事件吗?
  • 如果数据保存在数据库中,那么“每次”用户单击单元格或更改单元格中的值时都会保存数据......嗯......这看起来就像你可能正在崩溃数据库。你确定一个“外部”机制,比如“保存”按钮或者当焦点“离开”网格本身可能是更好的方法吗?每次用户进行一次更改时都保存数据似乎很奇怪。
  • 如果用户单击是,则需要保存。这是我正在从事的工作的要求之一。
  • 那么您可能需要考虑使用不同的事件,例如网格CellValueChanged 事件。当用户在单元格中进行更改然后“离开”该单元格时,它只会触发一次。
  • 谢谢约翰。我找到了使用这两个事件的解决方案。如果我只使用 CellValueChanged ,那么一旦用户单击下拉列表中的选项,我就会失去消息框的功能。用户需要点击离开才能出现消息框。

标签: c# winforms datagridcomboboxcolumn


【解决方案1】:

我找到了解决方案。我同时使用 CellValueChanged 和 CurrentCellDirtyStateChanged 来使其工作。我的代码如下。

namespace WindowsFormsApp3
{
    public partial class Form1 : Form
    {
        List<Team> teamList = new List<Team>();
        List<Team_Colour> teamColourList = new List<Team_Colour>();
        DataGridViewComboBoxColumn cb = new DataGridViewComboBoxColumn();
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            teamList.Add(new Team { name = "Test A", Colour_ID = 1});
            teamList.Add(new Team { name = "Test B", Colour_ID = 2 });
            teamList.Add(new Team { name = "Test C", Colour_ID = 3 });
            teamList.Add(new Team { name = "Test D", Colour_ID = 4 });

            dataGridView1.DataSource = teamList;
            dataGridView1.Columns[1].Visible = false;
            cb.HeaderText = "Colour";

            teamColourList.Add(new Team_Colour { Colour_ID = 1, Colour_Name = "None" });
            teamColourList.Add(new Team_Colour { Colour_ID = 2, Colour_Name = "Green" });
            teamColourList.Add(new Team_Colour { Colour_ID = 3, Colour_Name = "Blue" });
            teamColourList.Add(new Team_Colour { Colour_ID = 4, Colour_Name = "Red" });


            cb.DataSource = teamColourList;
            cb.DisplayMember = "Colour_Name";
            cb.ValueMember = "Colour_ID";
            cb.DataPropertyName = "Colour_ID";


            dataGridView1.Columns.Insert(1, cb);

        }

        private void DataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }

        private void DataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {

            DialogResult dialogResult = MessageBox.Show("Are you sure", "Saving", MessageBoxButtons.YesNo);
            if (dialogResult == DialogResult.Yes)
            {

            }
            else if (dialogResult == DialogResult.No)
            {

            }
        }
    }
}

【讨论】:

  • 您可以通过仅使用CellValueChanged 事件来完成同样的事情。事实上,使用这种方法,如果希望用户将值“键入”到非组合框单元格中……您将遇到更大的问题。自己尝试一下……尝试编辑其他非组合框单元格之一。
  • 我使用了 CellValueChanged 事件。正如之前的评论中提到的,消息框仅在我单击组合框时才会出现,这将不起作用,因为我需要立即出现消息框,除非我误解了您,并且这些方法是使用 CellValueChanged 实现它的方法。为了处理非组合框单元格,我将添加代码来处理仅当它是组合框列 id 的事件。
  • 如果在 CurrentCellDirtyStateChanged 内,代码仅在“组合框”更改时才调用网格 CommitEdit,那么这应该可以工作。
  • 但是,正如我之前所说,如果您每次都调用数据库来保存这些更改网格单元格值的一个更改......这是一个“要求”......那么我会质疑是谁在做这个要求。我可以向您保证,数据库管理员不会支持这种对数据库的冲击。每次用户更改其中一个单元格时更新数据库的整个想法……在几乎所有情况下都令人不悦。但是,如果这是您必须满足的要求,那就去做吧。
猜你喜欢
  • 2013-09-23
  • 1970-01-01
  • 2018-08-09
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多