2015-05-20 2 views
3

У меня возникла проблема с FlowLayoutPanel, в то время как его дочерние элементы изменяются по размеру в событии ClientSizeChanged FlowLayoutPanel.FlowLayoutPanel показывает горизонтальную полосу прокрутки с шириной внутренней панели, равной ширине размера клиента

Я пытаюсь изменить размеры детей горизонтально, когда изменяется FlowLayoutPanel. Проблема в том, что даже если край дочернего элемента равен 0, а заполнение FlowLayoutPanel также равно 0, после выполнения обработчика событий ClientSizeChanged FlowLayoutPanel показывает свою горизонтальную полосу прокрутки , тогда как ширина дочернего элемента точно такая же, как и FlowLayoutPanel.ClientSize.Width.

Я попытался переместить код для изменения размера, но я все равно получаю тот же результат.

Это пример, чтобы продемонстрировать эту проблему, есть один FlowLayoutPanel со следующими свойствами изменяется от по умолчанию:

  • AutoScroll = истинный
  • FlowDirection = Перевернутые
  • Margin = 0,0,0, 0
  • Name = потоки1
  • BackColor = Красный

Там также регулярная панель внутри FlowLayoutPanel:

  • Margin = 0,0,0,0
  • Name = panel1
  • BackColor: Синий

И, наконец, таймер с интервал 1, который изменяет ширину FlowLayoutPanel и отключает себя, когда свойство HorizontalScroll.Visibile для FlowLayoutPanel истинно и показывает окно сообщения, которое объявляет ширину панели1 и ClientSize.Width потока1.

Вот код:

private void timer1_Tick(object sender, EventArgs e) 
    { 
     flow1.Width -= 1; 

     if (flow1.HorizontalScroll.Visible) 
     { 
      timer1.Enabled = false; 
      MessageBox.Show("Panel.Width = " + panel1.Width.ToString() + 
       ", FlowPanel.ClientWidth = " + flow1.ClientSize.Width.ToString()); 
     } 
    } 

    private void flow1_ClientSizeChanged(object sender, EventArgs e) 
    { 
     panel1.Width = flow1.ClientSize.Width; 
    } 

Что логика горизонтальной полосы прокрутки показываются, пока дети не переполняется размер клиента? И что самое главное, как предотвратить это?

ответ

1

Это проблема заказа события, макет вычисляется слишком рано. Автоматическая компоновка имеет несколько неприятных угловых шкафов, она также может быть бистабильной, когда макет перевертывается назад и вперед между двумя решениями. Вы можете увидеть это в своем тестовом приложении, добавив flow1.PerformLayout(); перед вызовом MessageBox.Show(), и вы увидите, что полоса прокрутки снова скрыта.

Именно поэтому метод SuspendLayout() существует. Программисты Winforms не используют его достаточно. По уважительной причине, это довольно сложно судить, когда вам это нужно. И они действительно не хотят этого. Основное правило заключается в том, что вы должны использовать его, если макет должен иметь дело с более чем одним изменением размера.

Что реальное исправление в тестовой программе:

private void timer1_Tick(object sender, EventArgs e) { 
    flow1.SuspendLayout(); 
    flow1.Width -= 1; 
    flow1.ResumeLayout(true); 
    // etc.. 
} 

И вы увидите, что она прекрасно работает сейчас, вы никогда не увидите окно сообщения.

+0

Спасибо Гансу, это было точное решение, которое я искал. Я собираюсь попробовать его в своем основном приложении, но он отлично работает в тестовом приложении. –

Смежные вопросы