Search code examples
c#winformseventscontrols

trying to find and use control using event without ASP


What I am trying to do is create a library of DataGridView functions that I can copy and paste AS IS into a program. For brevity all functions will reference that DataGridView as dgv.

As things stand now I have to go through and change every piece of copied code to reflect the current DataGridView Name. One obvious solution is to just name the DataGridView in every program to dgv.

But what I really want to do is when I raise an event get the Control from inside the event.

Here's what I've tried in addition to a failed attempt at using the ASP.net control.findcontrol.

code

    private void dgvSignals_MouseClick(object sender, MouseEventArgs e)
    {
        System.Windows.Forms.Control ctrl = sender as System.Windows.Forms.Control;
        if (ctrl != null)
        {
            string name = ctrl.Name;
            lstDebug.Items.Add("Control Name: " + name);

            System.Windows.Forms.Control parent = (System.Windows.Forms.Control)ctrl.Parent;
            string parentName = parent.Name;
            lstDebug.Items.Add("Parent name: " + parentName);

            Control A = FindControlByName(parent, name);
            if (A != null) 
            { 
                lstDebug.Items.Add("A.Name: " + A.Name);        // I get the correct Name dgvSignals
                lstDebug.Items.Add("A.Type: " + A.GetType());   // I get the correct Type dataGridView
            }
            else
            {
                lstDebug.Items.Add("Returned Null");
            }

            dgv_RowDelete(A, 6); // CS1503 Argument 1: cannot convert from 'System.Windows.Forms.Control' to 'System.Windows.Forms.DataGridView'
        }

    private Control FindControlByName(System.Windows.Forms.Control parent, string name)
    {
        foreach (Control c in parent.Controls)
        {
            if (c.Name == name)
                return c; //found
        }
        return null; //not found
    }

    private bool dgv_RowDelete(DataGridView dgv, int row2Remove)
    {
    }

I am really in over my head here.


Solution

  • As I understand it, the essence of your question is how to find and use control using event without ASP. In Winforms, the equivalent of FindControlByName is to use the string indexer of the Controls collection as shown below. However, I also notice that you're in a handler for a MouseClick occurring on dgvSignals which means that sender is already dgvSignals.


    Nevertheless, if you want to find this or any other control by name, it's pretty easy:

    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            dgvSignals.MouseClick += DgvSignals_MouseClick;
        }
    
        private void DgvSignals_MouseClick(object? sender, MouseEventArgs e)
        {
            if(sender is DataGridView dgv)
            {
                Debug.Assert(
                    dgv.Name == nameof(dgvSignals), 
                    "Expecting sender name is dgvSignals");
    
                // Find control by name without ASP
                var findByName = Controls[nameof(dgvSignals)] as DataGridView;
                Debug.Assert(
                    ReferenceEquals(findByName, dgv), 
                    "Expecting these to be the same object");
            }
            else
            {
                Debug.Assert(
                    false, 
                    "Expecting DataGridView");
            }
        }
    }
    

    If the DataGridView isn't at the top level (e.g. it's inside a TableLayoutPanel or other Control) you will have to IterateControlTree to find it.


    There is a subtext to your question where you want to call this library from any program with a DataGridView regardless of name. Using Extension Methods in your common library is one way.

    /// <summary>
    /// Custom functionality for any program with any DataGridView
    /// </summary>
    public static partial class DataGridViewExtensions
    {
        public static void WhoAmI(this DataGridView anyDataGridView)
        {
            var controlName =
                string.IsNullOrWhiteSpace(anyDataGridView.Name) ?
                    "Unnamed DataGridView" :
                    anyDataGridView.Name;
            MessageBox.Show($"{nameof(WhoAmI)} called by {controlName}");
        }
    }
    

    demo of WhoAmI popup

    Call extension

    private void DgvSignals_MouseClick(object? sender, MouseEventArgs e)
    {
        if(sender is DataGridView dgv)
        {
            // Call extension
            dgv.WhoAmI();
        }
        else
        {
            Debug.Assert(false, "Expecting DataGridView");
        }
    }