Reputation: 15
I'm trying to make a custom control, to show some data from a SQL source. The data should change in a method, which is triggered by a Timer control.
Let say, if I append all my needed data in stringbuffer and then I show this in long label is working. Every time label is repainted, there is no blinking.
But, if I want make more fancy look, I found only way to put controls in FLowLayoutPanel and build whole structure. Ok, it works, but every time the controls are drawn, I need to dispose them. If not, controls being added to infinity, and buffer overload.
But If I dispose() or clear() them, there is blinking every time controls are redrawn.
Is there a way to get rid of this blinking? Or maybe some other way to do my work?
My code:
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();
}
}
Upvotes: 1
Views: 2136
Reputation: 1
I find combining Vajura's method and wrap the update with SuspendLayout() / ResumeLayout() will completely remove the flickering.
// Declaration
CustomFLP m_doubleBufferFlowLayoutPanel;
void UpdatePanel()
{
m_doubleBufferFlowLayoutPanel.SuspendLayout();
// update the flow layout panel here
...
m_doubleBufferFlowLayoutPanel.ResumeLayout();
}
Upvotes: 0
Reputation: 1132
Create a custom flowLayoutPanel class and add this in its constructor
public class CustomFLP: FlowLayoutPanel
{
public CustomFLP() : base()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.UpdateStyles();
}
}
Then do everything the same way you are doing now except you create your flowlayout panel with CustomFLP instead of FlowLayoutPanel.
This adds a double buffer to your control, might not work with a lot of updates.
Upvotes: 2