2016-05-19 2 views
0

У меня есть TableLayoutPanel с полосой прокрутки (потому что общая высота элементов управления больше, чем высота TableLayoutPanel). Я пытаюсь прокручивать программно в следующую/предыдущую строку с помощью кнопок PageUp- и PageDown-Keys.TableLayoutPanel может только найти элементы управления по точкам, которые были в видимой области при запуске

Прокрутка работает, но только до тех пор, пока я хочу прокрутить до элемента управления, который был уже в видимой области, когда программа запустилась. Когда я пытаюсь получить Control дальше вниз (который тем временем вошел в видимую область), tlp.GetChildAtPoint(new Point(1, tlp.AutoScrollPosition.Y * -1 + 2)) возвращает null.

Может кто-нибудь, пожалуйста, помогите мне решить эту проблему?

Примечание: Я нашел обходное решение (см. Мой ответ), но я, конечно, открыт для других решений.


код, чтобы воспроизвести проблему:

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; 
     } 
    } 
} 
+0

Это является очень распространенной ошибкой использовать TLP для осуществления контроля сетки. Это не было сделано для этого, его единственная задача - обеспечить автоматическую компоновку. Если DataGridView вас не устраивает, тогда отправляйтесь за покупками, у каждого поставщика компонентов есть сетка wiz-bang. –

ответ

0

Я нашел решение избегая GetChildAtPoint -метод. Он проверяет местоположение каждого элемента управления первого столбца, чтобы получить первый видимый столбец.

Мне также пришлось заменить .AutoScrollPosition = ... на прокрутку до последнего элемента управления, а затем до нужного элемента управления (я хочу, чтобы элемент управления находился в верхней части видимой области).


изменил 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); 
    } 
} 
Смежные вопросы