【问题标题】:Add textchange event to datagridview cell将 textchange 事件添加到 datagridview 单元格
【发布时间】:2019-01-29 23:46:00
【问题描述】:

我想在 datagridview c# 中创建一个自动完成单元格。我希望在文本更改时动态填充 autocompletecustomsource。

我已尝试按照中的建议将 textChanged 事件处理程序添加到单元格 “How to get the text from current cell in datagridview textchanged event?”。有用。 但有时它崩溃并显示错误

Vschost32 Error, or memory access violation.

知道如何实现吗?

更新 1

我的代码

    private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        DataGridView dgv = sender as DataGridView;
        string headerText = dgv.Columns[dgv.CurrentCell.ColumnIndex].HeaderText.ToString();
        DataGridViewTextBoxEditingControl tb = e.Control as DataGridViewTextBoxEditingControl;
        removeAutoComplete(tb);
        if (headerText == "Kode Barang" && tb !=null)
        {
            tb.TextChanged += new EventHandler(tb_kodeBarang_TextChanged);
        }
        else if(headerText == "Nama Barang" && tb!=null)
        {
            tb.TextChanged += new EventHandler(tb_namaBarang_TextChanged);
        }  
    }
    private void removeAutoComplete(TextBox tb)
    {
        tb.TextChanged -= tb_kodeBarang_TextChanged;
        tb.TextChanged -= tb_namaBarang_TextChanged;
        tb.AutoCompleteMode = AutoCompleteMode.None;
    }
    private void tb_kodeBarang_TextChanged(object sender,EventArgs e)
    {
        TextBox tb = sender as TextBox;
        if (tb.Text.Length > 0 && tb.Text != "" && tb.Text != null)
        {
            tb.AutoCompleteMode = AutoCompleteMode.Suggest;
            tb.AutoCompleteSource = AutoCompleteSource.CustomSource;
            tb.AutoCompleteCustomSource = getStringCollection(tb.Text,"Kode");                
        }
    }
    private void tb_namaBarang_TextChanged(object sender, EventArgs e)
    {
        TextBox tb = sender as TextBox;
        if (tb.Text.Length > 0 && tb.Text != "" && tb.Text != null)
        {
            tb.AutoCompleteMode = AutoCompleteMode.Suggest;
            tb.AutoCompleteSource = AutoCompleteSource.CustomSource;
            tb.AutoCompleteCustomSource = getStringCollection(tb.Text,"Nama");
        }
    }

【问题讨论】:

  • 请显示完整的代码以获取参考和 TextChanged 事件。是否有任何关于控件仍然有效的检查?
  • 问题已被编辑。如何检查控件是否仍然有效?
  • 我不喜欢您处理初始设置的方式:您总是在显示事件中创建对 tb 的引用。然后清除旧手柄,然后设置新手柄。但是当切换到不同的单元格时,新单元格将有一个新的编辑控件。我相信您应该将 tb 存储为类级变量,检查 null,清除句柄,然后获取新的句柄并设置其句柄。崩溃的重现性如何?
  • 感谢先生的建议。所以我在 if (headerText == "Kode Barang" && e.control !=null) 之后移动 tb。那我应该检查什么? tb 还是事件处理程序?如果它是事件处理程序,我怎么知道它是否为空。崩溃发生在插入 1/2 行甚至编辑同一行中的不同列之后。
  • 建议编辑对于评论来说太长了,所以我把它写成答案。显然,它未经测试..

标签: c# datagridview


【解决方案1】:

这就是我要改变的:

您的代码:

private void dataGridView1_EditingControlShowing(object sender,
                           DataGridViewEditingControlShowingEventArgs e)
{
    DataGridView dgv = sender as DataGridView;
    string headerText = dgv.Columns[dgv.CurrentCell.ColumnIndex].HeaderText.ToString();
    DataGridViewTextBoxEditingControl tb = e.Control as DataGridViewTextBoxEditingControl;
    removeAutoComplete(tb);
    ...

建议修改:

 DataGridViewTextBoxEditingControl tb = null;  // keep reference

 private void dataGridView1_EditingControlShowing(object sender,
                           DataGridViewEditingControlShowingEventArgs e)
{
    DataGridView dgv = sender as DataGridView;
    string headerText = dgv.Columns[dgv.CurrentCell.ColumnIndex].HeaderText.ToString();
    if (tb != null) removeAutoComplete(tb);  // check for null and unhook old tb
    tb = e.Control as DataGridViewTextBoxEditingControl;
    ...

当编辑不同的单元格/行时,单元格将不会获得相同的 TextBox 控件,因此您不应依赖它是相同的;因此,取消挂钩可能会失败,也可能会失败。

实际上,需要进行另一项检查以获取正确类型的编辑控件;毕竟可能有 ComboBoxCells 或 CheckBoxCell 之类的东西..

也许像这样检查:

if (tb is TextBox)..

【讨论】:

  • 感谢@TaW 的建议,但它仍然崩溃了。 在 MYAPP.exe 中的 0x75C7D640 (shell32.dll) 处引发异常:0xC0000005:访问冲突读取位置 0x0031003D。
  • 很抱歉听到这个消息。你能确定崩溃的线路吗?
  • 关于program.cs Application.Run(new My_Form());
  • 不,这还不够好。你能让它在调试器仍然连接的情况下崩溃吗?你能在 VS 窗格中看到调用堆栈吗?你能描述一下它在哪个动作上崩溃吗? (输入单元格时,输入文本时?按“输入”时?离开单元格时?)这有模式吗?另外:你能显示更新自动完成源的代码吗?是在getStringCollection 吗?您是否为每次击键更改它,或者您是否检测到 CellEndEdit 的“Enter”键?
  • hmm 有任何引用来附加调试器并显示调用堆栈吗?据我所知,没有特定的模式。对于字符串集合,我每次在单元格上进行文本更改时都会更改它,例如文本框上的文本更改事件。
【解决方案2】:

这是给你最好的答案示例,亲爱的..

 private void dgvEntry_CellValidated(object sender, DataGridViewCellEventArgs e)
        {
                double iTotal,iQty,iPrice;

            try
            {
                var itmColumn = dgvEntry[e.ColumnIndex, e.RowIndex];
                if(itmColumn.OwningColumn.Index>0)
                {
                    iTotal = 0; iQty = 0; iPrice = 0;
                    foreach(DataGridViewRow row in dgvEntry.Rows)
                    {
            iQty = Convert.ToDouble(row.Cells[dgvDOentry.Columns["itQty"].Index].Value);
          iPrice = Convert.ToDouble(row.Cells[dgvDOentry.Columns["itRate"].Index].Value);
         row.Cells[dgvEntry.Columns["itTotal"].Index].Value = iQty * iPrice;
                    }
                }

            }

【讨论】:

  • 虽然此代码可能会回答问题,但最好附上解释为什么您的答案解决了原始提问者的问题,以帮助未来的用户。
  • 另外,我不是 C# 方面的专家,但这段代码看起来没有正确缩进 - 可能还有其他值得一看的东西(至少,你的函数声明的顶部需要是部分代码 sn-p)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-27
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-06
  • 2016-04-05
相关资源
最近更新 更多