C# 动态添加到TableLayoutPanel的行显示在不同的行位置
我正在尝试通过单击按钮将文本框动态添加到TableLayoutPanel。单击鼠标可选择一行。C# 动态添加到TableLayoutPanel的行显示在不同的行位置,c#,winforms,dynamic,position,tablelayoutpanel,C#,Winforms,Dynamic,Position,Tablelayoutpanel,我正在尝试通过单击按钮将文本框动态添加到TableLayoutPanel。单击鼠标可选择一行。 在选择行之后,单击按钮可在所选行号上插入文本框。 问题是,在不同选择的行上正确地显示文本框3或4次后,进一步单击按钮开始在随机行上显示文本框,即使调试时显示了正确的行号 我需要帮助,这里是完整的代码: public partial class Form1 : Form { private TableLayoutPanel _tableLayout; private int _selec
在选择行之后,单击按钮可在所选行号上插入文本框。
问题是,在不同选择的行上正确地显示文本框3或4次后,进一步单击按钮开始在随机行上显示文本框,即使调试时显示了正确的行号 我需要帮助,这里是完整的代码:
public partial class Form1 : Form
{
private TableLayoutPanel _tableLayout;
private int _selectedRow = -1;
public Form1()
{
InitializeComponent();
var button = new Button()
{
Text = "Add Text"
};
button.MouseClick += AddText;
this.Controls.Add(button);
_tableLayout = new TableLayoutPanel()
{
Dock = DockStyle.Fill,
AutoScroll = true,
AutoSize = true,
AutoSizeMode = AutoSizeMode.GrowAndShrink,
CellBorderStyle = TableLayoutPanelCellBorderStyle.Single
};
_tableLayout.MouseClick += SelectRow;
this.Controls.Add(_tableLayout);
}
private void SelectRow(object sender, MouseEventArgs e)
{
_selectedRow = GetRowColIndex(_tableLayout, e.Location).Value.Y;
}
private void AddText(object sender, MouseEventArgs e)
{
_tableLayout.ColumnStyles.Add(new ColumnStyle() { SizeType = SizeType.AutoSize });
_tableLayout.RowStyles.Add(new RowStyle() { SizeType = SizeType.AutoSize });
_tableLayout.Controls.Add(new TextBox(), 0, _selectedRow);
}
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);
}
}
公共部分类表单1:表单
{
私人桌面布局面板_桌面布局;
private int _selectedRow=-1;
公共表格1()
{
初始化组件();
var按钮=新按钮()
{
Text=“添加文本”
};
button.MouseClick+=添加文本;
此.Controls.Add(按钮);
_tableLayout=新建TableLayoutPanel()
{
Dock=DockStyle.Fill,
AutoScroll=true,
AutoSize=true,
AutoSizeMode=AutoSizeMode.growthandshrink,
CellBorderStyle=表格布局面板CellBorderStyle.Single
};
_tableLayout.MouseClick+=选择行;
this.Controls.Add(_tableLayout);
}
private void SelectRow(对象发送者,鼠标指针)
{
_selectedRow=GetRowColIndex(_tableLayout,e.Location).Value.Y;
}
私有void AddText(对象发送者,MouseEventArgs e)
{
_tableLayout.ColumnStyles.Add(新ColumnStyle(){SizeType=SizeType.AutoSize});
_tableLayout.RowStyles.Add(新的RowStyle(){SizeType=SizeType.AutoSize});
_tableLayout.Controls.Add(新文本框(),0,_selectedRow);
}
点?GetRowColIndex(表格布局面板tlp,点)
{
if(点X>tlp.宽度| |点Y>tlp.高度)
返回null;
int w=tlp.宽度;
int h=tlp高度;
int[]widths=tlp.GetColumnWidths();
int i;
对于(i=widths.Length-1;i>=0&&point.X=0&&point.Y
当前代码中缺少某些部分。它不考虑滚动条和当前TableLayoutPanel的DisplayRectangle。正如您在.Net源代码中看到的,该方法已经执行了这些计算,以获取每个单元格的坐标,并调用使用当前单元格的边界和剪贴簿初始化的类
您可以在代码中使用相同的逻辑或使用已知的度量,从事件中的e.CellBounds
参数检索单击的单元格边界
在这里的示例中,从TLP的MouseClick
事件中获取鼠标位置,并使用e.cellbunds.Contains(currentPointerLocation)
中的方法在单元格边界包含鼠标指针时绘制单元格背景,并使用存储在此处的两个字段中的当前坐标更新两个标签,对于semplicity:
Point currentPointerLocation = Point.Empty;
Rectangle currentCellBounds = Rectangle.Empty;
Point currentCell = Point.Empty;
private void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
{
if (e.CellBounds.Contains(currentPointerLocation)) {
currentCellBounds = e.CellBounds;
currentCell = new Point(e.Row, e.Column);
e.Graphics.FillRectangle(Brushes.Red, e.CellBounds);
}
else {
using (var brush = new SolidBrush(tableLayoutPanel1.BackColor)) {
e.Graphics.FillRectangle(brush, e.CellBounds);
}
}
}
private void tableLayoutPanel1_MouseClick(object sender, MouseEventArgs e)
{
currentPointerLocation = e.Location;
this.tableLayoutPanel1.Invalidate();
this.tableLayoutPanel1.Update();
lblCurrentCell.Text = currentCell.ToString();
lblCellBounds.Text = currentCellBounds.ToString();
}
使用这些值,可以更简单地确定当前单元格的坐标,并在向使用鼠标指针选定的单元格添加控件时使用这些坐标
例如,使用按钮(btnAddControl
)和ContextMenuStrip向TableLayoutPanel添加不同的控件:
private void btnAddControl_Click(object sender, EventArgs e)
{
tableLayoutPanel1.Controls.Add(new TextBox() {
Multiline = true, Text = "TextBox from Button", Dock = DockStyle.Fill }, currentCell.Y, currentCell.X);
}
// Each ToolStripMenuItem sub-item subscribes to the event using this handler
private void contextTLPMenu_Clicked(object sender, EventArgs e)
{
Control ctl = null;
switch ((sender as ToolStripMenuItem).Text)
{
case "TextBox":
ctl = new TextBox() { Multiline = true, Text = "TextBox from ContextMenu" };
break;
case "Button":
ctl = new Button() { Text = "A Button", ForeColor = Color.White };
break;
case "Panel":
ctl = new Panel() { BackColor = Color.LightGreen };
break;
default:
break;
}
if (ctl != null) {
ctl.Dock = DockStyle.Fill;
tableLayoutPanel1.Controls.Add(ctl, currentCell.Y, currentCell.X);
}
}
视觉效果: