Избавьтесь от мерцания при динамическом добавлении элементов управления в FlowLayoutpanel, запускаемом по таймеру

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

Скажем, если я добавлю все необходимые данные в строковый буфер, а затем покажу это в длинной метке, все будет работать. Каждый раз, когда этикетка перекрашивается, мигания нет.

Но, если я хочу сделать внешний вид более привлекательным, я нашел единственный способ поместить элементы управления в FLowLayoutPanel и построить всю структуру. Хорошо, это работает, но каждый раз, когда элементы управления рисуются, мне нужно их удалять. Если нет, то элементы управления добавляются до бесконечности и происходит перегрузка буфера.

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

Есть ли способ избавиться от этого мерцания? Или, может быть, какой-то другой способ сделать мою работу?

Мой код:

void timer_Tick(object sender, EventArgs e)
    {
        try
        {            
            GetMapData();
        }
        catch (Exception ex)
        {

        }
    }

  private void GetMapData()
  {
       DataSet ds = MapStatistics.GetMapData(top, bottom, left, right, idUnit, idCustomerTmp);
       DataTable activDriversForZones = ds.Tables["ActivDriversForZone"];
       DataTable zones zones = ds.Tables["Zones"];

        if (zones != null || zones.Rows.Count > 0)
        {
            ClearflpPanel(flpTest2);

            zonesDriverCount = 0;
            foreach (DataRow rowZones in zones.Rows)
            {

                string idZone = Convert.ToString(rowZones["id_zone"]);
                string title = Convert.ToString(rowZones["title"]);

                StringBuilder zoneDriver = new StringBuilder();

                Label labelRowZone = new Label();
                labelRowZone.Width = 400;
                labelRowZone.AutoSize = true;
                labelRowZone.Font = new System.Drawing.Font("Arial", 10, FontStyle.Bold);
                labelRowZone.Text = (title + ": ");

                flpTest2.Controls.Add(labelRowZone);

                Label labelRowDriver = new Label();
                foreach (DataRow rowDriver in activDriversForZones.Rows)
                {
                    string idUnit = Convert.ToString(rowDriver["id_unit"]);
                    string imsi = Convert.ToString(rowDriver["imsi"]);
                    string zoneIn = Convert.ToString(rowDriver["zone_in"]);

                    if (idZone == zoneIn)
                    {
                        zonesDriverCount++;
                        zoneDriver.Append(imsi + "/" + idUnit + ", ");
                        labelRowDriver.Text = (zoneDriver.ToString());
                    }

                    flpTest2.Controls.Add(labelRowDriver);
                }

            }
        } 
   }

   public void ClearflpPanel(FlowLayoutPanel flp)
    {
        zonesDriverCount = 0;
        List<Control> listControls = flp.Controls.Cast<Control>().ToList();

        foreach (Control control in listControls)
        {
            flpTest2.Controls.Clear();
            //flpTest2.Dispose();
        }
    }

person martin    schedule 19.11.2014    source источник
comment
При добавлении меток вы запускаете множество расчетов макета. Оберните этот код с помощью flpTest2.Suspend/ResumeLayout(). Имейте в виду, что FLP — очень плохая замена правильному элементу управления сеткой, например DataGridView.   -  person Hans Passant    schedule 19.11.2014


Ответы (2)


Создайте собственный класс flowLayoutPanel и добавьте его в свой конструктор.

public class CustomFLP: FlowLayoutPanel 
{
    public CustomFLP() : base()
    {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.UpdateStyles();
    }
}

Затем сделайте все так же, как вы делаете сейчас, за исключением того, что вы создаете панель потока с помощью CustomFLP вместо FlowLayoutPanel.

Это добавляет двойной буфер к вашему элементу управления, может не работать с большим количеством обновлений.

person Vajura    schedule 19.11.2014

Я считаю, что сочетание метода Vajura и обертывание обновления с помощью SuspendLayout() / ResumeLayout() полностью устранит мерцание.

// Declaration
CustomFLP m_doubleBufferFlowLayoutPanel;

void UpdatePanel()
{
    m_doubleBufferFlowLayoutPanel.SuspendLayout();

    // update the flow layout panel here
    ...

    m_doubleBufferFlowLayoutPanel.ResumeLayout();
}
person Jian    schedule 22.03.2017