【问题标题】:C# WinForms Combobox.DropDownStyle sometimes causing an exception when changedC# WinForms Combobox.DropDownStyle 有时会在更改时导致异常
【发布时间】:2019-10-28 14:34:40
【问题描述】:

我有一个表单,它使用 2 个组合框来选择一个作业和一个 SQL 查询来编辑/创建。如果组合框位于索引 0,我将 DropDownStyle 设置为 DropDownStyle.DropDown,以便用户可以编辑文本。当他们按下回车键时,它将根据他们使用的组合框创建一个新作业或查询,并将其添加到相应的框中。如果这些框位于任何其他索引处,我将 DropDownStyle 设置为 DropDownStyle.DropDownList,因此文本不可编辑。

有时,在更改 DropDownStyle 时,会引发 System.AccessViolationException:

Exception

我已将更改 DropDownStyle 的代码封装在 try-catch 块中,并将断点放在 catch 块中,但它不会在这些点处中断,而是在显示表单的调用处中断。 这是表单中改变 DropDownStyle 的 2 个方法:

        private void CboJob_SelectedIndexChanged(object sender, EventArgs e)
        {

            try
            {
                cboJob.DropDownStyle = ComboBoxStyle.DropDownList;
            }
            catch (Exception ex)
            {
                throw;
            }
            txtSQL.TextChanged -= TxtSQL_TextChanged;
            txtSQL.Text = "";
            txtSQL.Enabled = false;
            txtSQL.TextChanged += TxtSQL_TextChanged;
            cboQuery.Items.Clear();
            if (cboJob.SelectedIndex > 0)
            {
                cboQuery.Enabled = true;
                btnDeleteJob.Enabled = true;
                cboQuery.Items.Add("<New Query>");
                cboQuery.Items.AddRange(_jobs[cboJob.SelectedIndex - 1].Queries.ToArray());
                if (cboQuery.Items.Count > 1)
                {
                    cboQuery.SelectedIndex = 1;
                }
                else
                {
                    cboQuery.SelectedIndex = 0;
                }
            }
            else
            {
                cboQuery.Enabled = false;
            }
            if (cboJob.SelectedIndex == 0)
            {
                try
                {
                    cboJob.DropDownStyle = ComboBoxStyle.DropDown;
                }
                catch (Exception ex)
                {
                    throw;
                }
            }
        }
        private void CboQuery_SelectedIndexChanged(object sender, EventArgs e)
        {

            try
            {
                cboQuery.DropDownStyle = ComboBoxStyle.DropDownList;
            }
            catch (Exception ex)
            {
                throw;
            }
            if (cboQuery.SelectedIndex > 0)
            {
                if (_jobs[cboJob.SelectedIndex - 1].Queries.Count > 0)
                {
                    txtSQL.Enabled = true;
                    btnDeleteQuery.Enabled = true;
                    txtSQL.Text = _jobs[cboJob.SelectedIndex - 1].Queries[cboQuery.SelectedIndex - 1].Sql;
                }
                else
                {
                    btnDeleteQuery.Enabled = false;
                    txtSQL.Enabled = false;
                }
            }
            else
            {
                btnDeleteQuery.Enabled = false;
                txtSQL.Enabled = false;
            }
            if (cboQuery.SelectedIndex == 0)
            {
                try
                {
                    cboQuery.DropDownStyle = ComboBoxStyle.DropDown;
                }
                catch (Exception ex)
                {
                    throw;
                }
            }
        }

这是显示表单的方法:

        private void BtnEdit_Click(object sender, EventArgs e)
        {
            var frmSQL = new EditSQLForm();

            try
            {
                if (frmSQL.ShowDialog() == DialogResult.OK)//this is the line it breaks at
                {
                    _jobs = frmSQL.Jobs;
                    Save();
                    GetData();
                }
            }
            catch (Exception ex)
            {

                throw;
            }
            frmSQL.Dispose();
        }

我认为 try-catch 块没有捕获它的原因是抛出异常的代码是一个名为“comctl32.dll”的 Windows DLL。如果我打开本机代码调试,我会得到这个异常:

native code exception

我到处寻找有关此的信息,但找不到任何有用的信息。我在电脑上进行了内存测试,结果还可以。有什么想法吗?

谢谢!

【问题讨论】:

  • 当您设置 ComboBox 的DropDownStyle 时,将重新创建控件的句柄。它以前的句柄不再有效。

标签: c# winforms combobox


【解决方案1】:

乍一看有问题

if (_jobs[cboJob.SelectedIndex - 1].Queries.Count > 0)

cboJob.SelectedIndex 为 0 时会在此处抛出异常。尝试添加一个额外的条件(下面是你的代码+我在修改行中的评论):

        private void CboQuery_SelectedIndexChanged(object sender, EventArgs e)
        {

            try
            {
                cboQuery.DropDownStyle = ComboBoxStyle.DropDownList;
            }
            catch (Exception ex)
            {
                throw;
            }
            if (cboQuery.SelectedIndex > 0 && cboJob.SelectedIndex > 0) // ADDITIONAL CONDITION!
            {
                if (_jobs[cboJob.SelectedIndex - 1].Queries.Count > 0)
                {
                    txtSQL.Enabled = true;
                    btnDeleteQuery.Enabled = true;
                    txtSQL.Text = _jobs[cboJob.SelectedIndex - 1].Queries[cboQuery.SelectedIndex - 1].Sql;
                }
                else
                {
                    btnDeleteQuery.Enabled = false;
                    txtSQL.Enabled = false;
                }
            }
            else
            {
                btnDeleteQuery.Enabled = false;
                txtSQL.Enabled = false;
            }
            if (cboQuery.SelectedIndex == 0)
            {
                try
                {
                    cboQuery.DropDownStyle = ComboBoxStyle.DropDown;
                }
                catch (Exception ex)
                {
                    throw;
                }
            }
        }

这应该有助于避免代码中的负索引。

【讨论】:

    猜你喜欢
    • 2018-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    相关资源
    最近更新 更多