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.
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}");
}
}
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");
}
}