问题描述:

I have a TableLayoutPanel with a scrollbar (because the total height of the Controls is bigger than the height of the TableLayoutPanel). I try to scroll programmatically to the next/previous row with the PageUp- and PageDown-Keys.

Scrolling works, but only as far as I want to scroll to a Control that was already in the visible area when the program started. When I try to get a Control further down (that has meanwhile entered the visible area), tlp.GetChildAtPoint(new Point(1, tlp.AutoScrollPosition.Y * -1 + 2)) returns null.

Can someone please help me to resolve this issue?

Note: I found a workaround (see my answer), but I am of course open to other solutions.


Code to reproduce the problem:

public class FormTLPTest : Form

{

TableLayoutPanel tlp;

public FormTLPTest()

{

Height = 200;

Width = 200;

KeyPreview = true;

tlp = new TableLayoutPanel();

tlp.Dock = DockStyle.Fill;

tlp.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;

tlp.AutoScroll = false;

tlp.VerticalScroll.Visible = true;

tlp.HorizontalScroll.Visible = false;

tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 40));

Controls.Add(tlp);

tlp.SuspendLayout();

for (int i = 0; i < 20; i++)

{

Label lb2 = new Label();

lb2.Margin = new Padding(0);

lb2.Dock = DockStyle.Fill;

lb2.BackColor = Color.White;

lb2.Text = "Line " + i;

tlp.Controls.Add(lb2, 0, i);

tlp.RowStyles.Add(new RowStyle(SizeType.Absolute, 18));

tlp.RowCount++;

}

tlp.ResumeLayout();

tlp.AutoScroll = true;

KeyDown += FormTLPTest_KeyDown;

}

private void FormTLPTest_KeyDown(object sender, KeyEventArgs e)

{

if (e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown || e.KeyCode == Keys.Next)

{

Control currentTopControl = tlp.GetChildAtPoint(new Point(1, tlp.AutoScrollPosition.Y * -1 + 2));

int currentRow = 0;

if (currentTopControl != null)

currentRow = tlp.GetPositionFromControl(currentTopControl).Row;

int nextRow = -1;

if (e.KeyCode == Keys.PageUp)

nextRow = currentRow - 1;

else

nextRow = currentRow + 1;

if (nextRow < 0 || nextRow > tlp.RowCount - 1)

return;

Control nextTopControl = tlp.GetControlFromPosition(0, nextRow);

tlp.AutoScrollPosition = nextTopControl.Location;

}

}

}

网友答案:

I found a solution avoiding the GetChildAtPoint-method. It checks the location of every control of the first column to get the first visible column.

I also had to replace .AutoScrollPosition = ... with a scroll to the last control and then to the desired control (I want the control to be at the top of the visible area).


changed KeyDown-listener:

private void FormTLPTest_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown || e.KeyCode == Keys.Next)
    {
        int currentRow = 0;
        for (int y=0;y<tlp.RowCount;y++)
        {
            Control c = tlp.GetControlFromPosition(0, y);
            if (c.Location.Y >= 0)
            {
                currentRow = y;
                break;
            }
        }

        int nextRow = -1;
        if (e.KeyCode == Keys.PageUp)
            nextRow = currentRow - 1;
        else
            nextRow = currentRow + 1;

        if (nextRow < 0 || nextRow > tlp.RowCount - 1)
            return;

        Control nextTopControl = tlp.GetControlFromPosition(0, nextRow);
        tlp.ScrollControlIntoView(tlp.GetControlFromPosition(0, tlp.RowCount - 1));
        tlp.ScrollControlIntoView(nextTopControl);
    }
}
相关阅读:
Top