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

时间:2013-03-16 12:53:10

标签: c# winforms tablelayoutpanel

我有一个TableLayoutPanel,我想在我点击的单元格中添加一个控件。

问题是我无法确定我在运行时点击的单元格。

如何确定点击的单元格?

4 个答案:

答案 0 :(得分:8)

您可以使用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);
}

用法:

private void tableLayoutPanel1_Click(object sender, EventArgs e)
{
    var cellPos = GetRowColIndex(
        tableLayoutPanel1,
        tableLayoutPanel1.PointToClient(Cursor.Position));
}

但请注意,如果单元格尚未包含控件,则仅引发click事件。

答案 1 :(得分:3)

这对我有用:

[TestMethod]
public void TestContainer()
{
    var container = MyContainer.Container.GetInstance<DbContext>();
    var parentContext = container.GetInstance<MyContext>();
    var childContext = container.GetInstance<MyContext>();

    // This call will fail
    container.Verify();
}

请注意,我的tableLayoutPanel是全局声明的,因此我可以使用它而不必将其传递给每个函数。另外,tableLayoutPanel和其中的每个Panel都是以编程方式在其他地方创建的(我的表单[design]完全是空白的。)

答案 2 :(得分:2)

我的回答基于@Mohammad Dehghan上面的答案,但有几个好处:

  • 现在考虑垂直滚动
  • 列的顺序正确(从i=0开始,而不是i=length),这意味着以正确的顺序处理不同宽度或高度的列

以下是代码的更新版本:

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

答案 3 :(得分:0)

Nick的答案是最好的解决方案,除了可以使TableLayoutPanels通用(在单元格中包含不同类型的控件)。只需将显式的“ Panel”类型更改为“ 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) + ")");
}

这很好用,不需要做坐标数学来找到被单击的单元格。