简体   繁体   English

如何确定在TableLayoutPanel中单击的单元格?

[英]How do I determine the cell being clicked on in a TableLayoutPanel?

I have a TableLayoutPanel and I want to add a control to the cell that I click on. 我有一个TableLayoutPanel ,我想在我点击的单元格中添加一个控件。

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: 您可以使用GetColumnWidthsGetRowHeights方法来计算单元格行和列索引:

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. 但请注意,如果单元格尚未包含控件,则仅引发click事件。

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. 请注意,我的tableLayoutPanel是全局声明的,因此我可以使用它而不必将其传递给每个函数。 Also, both the tableLayoutPanel and each Panel within it are created completely programatically elsewhere (my form [design] is completely blank). 另外,tableLayoutPanel和其中的每个Panel都是以编程方式在其他地方创建的(我的表单[design]完全是空白的)。

My answer is based on @Mohammad Dehghan 's answer above but has a couple of advantages: 我的回答是基于@Mohammad Dehghan的回答,但有几个优点:

  • It now takes into account vertical scrolling 它现在考虑垂直滚动
  • The columns are in the correct order (starts at i=0 instead of i=length ), meaning columns of different widths or heights are processed in the correct order 列的顺序正确(从i=0开始而不是i=length ),这意味着以正确的顺序处理不同宽度或高度的列

Here 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. 尼克的回答是最好的解决方案,除了它可以为包含不同类型的控件的TableLayoutPanel制作通用的。 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. 这很有效,不需要进行坐标数学来查找单击了哪个单元格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM