You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义DataGridView控件中访问窗体的DataGridView引用?

问题描述

我想在自定义的smartdatagridview控件中,从Form1.cs类传入并访问仅在Form1.cs中使用的dataGridView1的引用。原因是我的Windows应用的每个窗体中都会有一个新的DataGridView(名称均不同),这些控件的引用需要被该自定义DataGridView用于特定用途。请问是否可以实现?如果不行,有什么替代方案?

现有代码
public partial class smartdatagridview : DataGridView
{
    public smartdatagridview()
    {
        InitializeComponent();
    }
    
    private TextBox textBox;

    protected override void OnEnter(EventArgs e)
    {
        base.OnEnter(e);
        CurrentCell = this[0, 0]; 
        BeginEdit(true);
    }
    
    protected override void OnEditingControlShowing(DataGridViewEditingControlShowingEventArgs e)
    {
        base.OnEditingControlShowing(e);

        if (CurrentCell.ColumnIndex == 0 && e.Control is TextBox)
        {
            textBox = (TextBox)e.Control;
            textBox.TextChanged -= Text_Changed;
            textBox.KeyDown -= Key_down;
            textBox.Enter -= Key_Enter;
            textBox.TextChanged += Text_Changed;
            textBox.KeyDown += Key_down;
            textBox.Enter +=Key_Enter;
        }
        else
        {
            textBox = null;
        }
    }

    protected override void OnCellEndEdit(DataGridViewCellEventArgs e)
    {
        base.OnCellEndEdit(e);
        if (textBox != null)
        {
            textBox.TextChanged -= Text_Changed;
            textBox.KeyDown -= Key_down;
            textBox.Enter -= Key_Enter;
            textBox = null;
        }
        if (this.CurrentCell.ColumnIndex == 0)
        {
            if (dataGridView1.Rows.Count > 0)  // 报错:找不到dataGridView1
            {
                this.CurrentCell.Value = dataGridView1.SelectedRows[0].Cells[1].Value.ToString(); // 报错
                dataGridView1.Visible = false;  // 报错
            }
        }
    }
}
解决方案

完全可以实现,推荐两种实用方案:

方案一:给自定义控件加公共属性传引用

在smartdatagridview类里新增一个公共属性,用来接收外部传入的目标DataGridView:

public partial class smartdatagridview : DataGridView
{
    // 新增属性,用来存外部传入的DataGridView引用
    public DataGridView TargetDataGridView { get; set; }

    public smartdatagridview()
    {
        InitializeComponent();
    }
    
    // 原有代码保持不变...

    protected override void OnCellEndEdit(DataGridViewCellEventArgs e)
    {
        base.OnCellEndEdit(e);
        if (textBox != null)
        {
            textBox.TextChanged -= Text_Changed;
            textBox.KeyDown -= Key_down;
            textBox.Enter -= Key_Enter;
            textBox = null;
        }
        if (this.CurrentCell.ColumnIndex == 0)
        {
            // 替换原来的dataGridView1为TargetDataGridView,先判空防报错
            if (TargetDataGridView != null && TargetDataGridView.Rows.Count > 0)  
            {
                this.CurrentCell.Value = TargetDataGridView.SelectedRows[0].Cells[1].Value.ToString(); 
                TargetDataGridView.Visible = false;  
            }
        }
    }
}

然后在窗体(比如Form1.cs)里,初始化自定义控件时把目标DataGridView传进去:

// 假设你的自定义控件实例叫smartDataGridView1
smartDataGridView1.TargetDataGridView = dataGridView1;

方案二:用事件通知窗体执行操作(解耦更彻底)

如果不想让自定义控件直接依赖外部的DataGridView,用事件触发窗体自己处理逻辑更合理:

  1. 先在自定义控件里定义事件和参数类:
public partial class smartdatagridview : DataGridView
{
    // 定义事件,用来通知窗体需要执行相关操作
    public event EventHandler<CellEndEditOperationArgs> OnNeedTargetGridOperation;

    // 自定义事件参数,用来传递当前单元格等需要的数据
    public class CellEndEditOperationArgs : EventArgs
    {
        public DataGridViewCell CurrentCell { get; set; }
    }

    public smartdatagridview()
    {
        InitializeComponent();
    }
    
    // 原有代码保持不变...

    protected override void OnCellEndEdit(DataGridViewCellEventArgs e)
    {
        base.OnCellEndEdit(e);
        if (textBox != null)
        {
            textBox.TextChanged -= Text_Changed;
            textBox.KeyDown -= Key_down;
            textBox.Enter -= Key_Enter;
            textBox = null;
        }
        if (this.CurrentCell.ColumnIndex == 0)
        {
            // 触发事件,把当前单元格传递给窗体
            OnNeedTargetGridOperation?.Invoke(this, new CellEndEditOperationArgs { CurrentCell = this.CurrentCell });
        }
    }
}
  1. 在窗体(Form1.cs)里订阅这个事件,处理具体逻辑:
public Form1()
{
    InitializeComponent();
    // 订阅自定义控件的事件
    smartDataGridView1.OnNeedTargetGridOperation += SmartDataGridView1_OnNeedTargetGridOperation;
}

private void SmartDataGridView1_OnNeedTargetGridOperation(object sender, smartdatagridview.CellEndEditOperationArgs e)
{
    if (dataGridView1.Rows.Count > 0)
    {
        e.CurrentCell.Value = dataGridView1.SelectedRows[0].Cells[1].Value.ToString();
        dataGridView1.Visible = false;
    }
}

方案选择建议

  • 方案一:实现简单直接,适合逻辑简单的小场景;
  • 方案二:遵循面向对象的解耦原则,自定义控件不用关心外部控件的细节,只负责触发事件,更适合复杂项目或需要复用自定义控件的场景。

内容的提问来源于stack exchange,提问作者ankit goel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 16:42:47