I have a TableLayoutPanel
and I want to add a control to the cell that I click on.
The problem is that I can't determine the cell that I click on at run time.
How do I determine the cell being clicked on?
I have a TableLayoutPanel
and I want to add a control to the cell that I click on.
The problem is that I can't determine the cell that I click on at run time.
How do I determine the cell being clicked on?
You can use GetColumnWidths
and GetRowHeights
methods to calculate the cell row and column index:
Point? GetRowColIndex(TableLayoutPanel tlp, Point point)
{
if (point.X > tlp.Width || point.Y > tlp.Height)
return null;
int w = tlp.Width;
int h = tlp.Height;
int[] widths = tlp.GetColumnWidths();
int i;
for (i = widths.Length - 1; i >= 0 && point.X < w; i--)
w -= widths[i];
int col = i + 1;
int[] heights = tlp.GetRowHeights();
for (i = heights.Length - 1; i >= 0 && point.Y < h; i--)
h -= heights[i];
int row = i + 1;
return new Point(col, row);
}
Usage:
private void tableLayoutPanel1_Click(object sender, EventArgs e)
{
var cellPos = GetRowColIndex(
tableLayoutPanel1,
tableLayoutPanel1.PointToClient(Cursor.Position));
}
But notice that the click event only is raised if the cell does not already contain a control.
[Browsable(false)]
attribute, but they exist, and if you use my code, you'll see that they will work. –
Oleograph This worked for me:
public TableLayoutPanel tableLayoutPanel { get; set; }
private void Form_Load(object sender, EventArgs e)
{
foreach (Panel space in this.tableLayoutPanel.Controls)
{
space.MouseClick += new MouseEventHandler(clickOnSpace);
}
}
public void clickOnSpace(object sender, MouseEventArgs e)
{
MessageBox.Show("Cell chosen: (" +
tableLayoutPanel.GetRow((Panel)sender) + ", " +
tableLayoutPanel.GetColumn((Panel)sender) + ")");
}
Note that my tableLayoutPanel is declared globally so that I can just use it without having to pass it to each function. Also, both the tableLayoutPanel and each Panel within it are created completely programatically elsewhere (my form [design] is completely blank).
My answer is based on @Mohammad Dehghan's answer above but has a couple of advantages:
i=0
instead of i=length
), meaning columns of different widths or heights are processed in the correct orderHere is the updated version of the code:
public Point? GetIndex(TableLayoutPanel tlp, Point point)
{
// Method adapted from: stackoverflow.com/a/15449969
if (point.X > tlp.Width || point.Y > tlp.Height)
return null;
int w = 0, h = 0;
int[] widths = tlp.GetColumnWidths(), heights = tlp.GetRowHeights();
int i;
for (i = 0; i < widths.Length && point.X > w; i++)
{
w += widths[i];
}
int col = i - 1;
for (i = 0; i < heights.Length && point.Y + tlp.VerticalScroll.Value > h; i++)
{
h += heights[i];
}
int row = i - 1;
return new Point(col, row);
}
Nick's answer was the best solution, except that it can be made generic for TableLayoutPanels that contain different kinds of controls in the cells. Just change the explicit "Panel" type to "Control":
public TableLayoutPanel tableLayoutPanel { get; set; }
private void Form_Load(object sender, EventArgs e)
{
foreach (Control c in this.tableLayoutPanel.Controls)
{
c.MouseClick += new MouseEventHandler(ClickOnTableLayoutPanel);
}
}
public void ClickOnTableLayoutPanel(object sender, MouseEventArgs e)
{
MessageBox.Show("Cell chosen: (" +
tableLayoutPanel.GetRow((Control)sender) + ", " +
tableLayoutPanel.GetColumn((Control)sender) + ")");
}
This works great and doesn't require doing coordinate math to find which cell was clicked.
PictureEdit ped = new PictureEdit();
ped.MouseClick += new MouseEventHandler((o, a) => your code);
© 2022 - 2025 — McMap. All rights reserved.