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

问题描述 投票:0回答:5

我有一个

TableLayoutPanel
,我想向我单击的单元格添加一个控件。

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

如何确定被点击的单元格?

c# winforms tablelayoutpanel
5个回答
16
投票

您可以使用

GetColumnWidths
GetRowHeights
方法来计算单元格行索引和列索引:

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

但请注意,仅当单元格尚未包含控件时才会引发单击事件。


4
投票

这对我有用:

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

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


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

0
投票

Nick 的答案是最好的解决方案,只不过它可以成为单元格中包含不同类型控件的 TableLayoutPanel 的通用解决方案。 只需将显式的“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) + ")");
}

这非常有效,不需要进行坐标数学来查找单击了哪个单元格。


0
投票

PictureEdit ped = new PictureEdit(); ped.MouseClick += new MouseEventHandler((o, a) => 你的代码);

© www.soinside.com 2019 - 2024. All rights reserved.