Avoid reload/redraw all components when swapping TabPages - c#

I have multiple TabPages on a TabControl. Some of these TabPages contain up to 100 Panels in a FlowLayoutPanel. Each of these Panels also contain a bunch of different controls...
The issue is simple: when I swap between TabPages, the one containing lots of controls take ages (1-2 seconds) to load.
I would like them not to lose "focus", to keep the components in memory or something when left for another tab, so that they don't have to reload everything when we come back on it.
Is it even possible? Or is it the drawing itself that take all this time? I do not do operations when changing tabs. Just displaying them.
Clarification edits:
Hum, maybe I was not clear enough. The problem is not how the stuff is drawn when being loaded. I have fixed this issue my own way (working with selected tab events). My problem is the time taken by the page to actually load. When I enter the TabPage containing lots of controls (in FlowLayoutPanel), it will load for about 1-2 sec THEN be displayed. I would like that to be almost instant, all controls being already available or something. But maybe it is not possible? Maybe it is the time taken to draw all those controls that is long?
What's weird is that it takes less time to actually generate all those panels (100 in less than 0.5) for the first time, than to redisplay them when leaving/entering the page after.
The displaying is also instant when coming from Minimized state (the form itself). I would like that to be the same when changing form state than swapping between tabs.

This is known issue with FlowLayoutPanel when having many controls inside. It tries to layout all of the controls and each time control is positioned part of the screen is redrawn.
To reduce this, try to enable double buffering on your form or FlowLayoutPanel control. This allows to do all rendering in memory first and swap buffers once when it is done.
Add this code:
public static void SetDoubleBuffered(System.Windows.Forms.Control c)
{
//Taxes: Remote Desktop Connection and painting
//http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
if (System.Windows.Forms.SystemInformation.TerminalServerSession)
return;
System.Reflection.PropertyInfo aProp =
typeof(System.Windows.Forms.Control).GetProperty(
"DoubleBuffered",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
aProp.SetValue(c, true, null);
}
Then just call this on your form or control.
SetDoubleBuffered(mainForm);
SetDoubleBuffered(myFlowPanel);

Related

Developing multi tab windows

let's say I want to make program settings menu like:
Many tab options that change the layout of the rest of the window
My program is in C# and I'm making it in Visual Studio
I tried to do it 2 ways:
Make the window super large with all possible layouts in the Form designer and then just resizing it to fit one of them at the time but this method works for like 4 tabs when you can fit them all at 1 screen. If it's large you have to work with slide bars and that's really impractical, laggy and for many tabs you even have to search them
Not using Form designer at all and hand write all the declarations, positions, sizes, colors etc. But like this it takes pretty a while even just to set up 1 button and there is no way I can fast see how it looks like
So the question is: Is there a magic way I don't know about to do this? And how is this made professionally?
Simple solution for small number of views
You can use a TextBox and ListView docked in a Panel docked left.
And a ControlTab docked fill in a panel named for example PanelMain docked fill at right with visible at false.
You will create any tabpage as option. In each tabpage you will put a panel docked fill and dedicated content in. On the listview item click event or itemchange, you will set the tabpage panel parent to PanelMain.
The little problem can be about spacing and the code file can be large (regions can be used).
Advanced solution more clean for several views
You can use the standard multipage pattern with one form per option/view, and do the same thing as exposed previously.
You create one form per view and put a panel docked fill embedding controls.
When the user click on the menu, you set the form main panel parent to the option form or the main panel of the options form.
I hope I haven't written too badly in unverified English.
Feel free to open any new question centered on any atomic and code problem on this subject.

How to prevent premature painting of MemoEdit control when the form is loading

How to prevent premature painting of MemoEdit control when the form is loading?
I have a form which is DevExpress.XtraBars.Docking.ControlContainer.
Red area in the pic.1 is the devexpress LayoutControl which consists of a bunch of LayoutControlItems, almost all of them have a TextEdit editors, but the second one from top is MemoEdit.
In the pic.2 is the what i see when the form is loading (after i called Show()).
As you can see, other controls are not drawn or displayed at the moment, but the MemoEdit do. I tried to use LockWindowUpdate, Begin/End Update, SuspendLayout but isn't working.
I would like to know what are reasons of this behaviour.
I want to specify something. Even when form is loaded and the LayoutControl was once filled with controls, MemoEdit still doing strange things, for example when I am switch between horizontal tabs (pic. 3 and pic. 4). At the moment when I select tab, that was already once "loaded" MemoEdit starts painting at old tab.

What are the side effects of Control.Controls.Add in Winforms?

I am trying to dynamically create a rather large TableLayoutPanel for an application I'm working on. As I've read from other questions, the TableLayoutPanel class suffers from significant performance problems when handling large and changing contents; I have, however, come too far to switch to something else just now.
I have been able to get around most of the issues by suspending layout before adding controls to the individual cells. One problem remains - when the table is first shown, it appears to take a little time before the background colors (just white) and everything else ready to be shown - like just a little less than a second of ugliness. I have tried doing all layout on startup, so that no calculations remain when the control is finally added, but the first drawing of it remains ugly. The weird thing is that when the control is shown again later (I keep it in memory instead of recreating it all the time) after having been removed from the main form for a while, it appears right away without any layouting. This leads me to believe that something happens when I first add the control to a child control of the main form, something I haven't reproduced in my own layouting - the question is, what? In order to force layout of the control right after its initialization, but before it is first shown, I do the following:
table.SuspendLayout();
// Create a whole lot of controls here and add them to the TableLayoutPanel
table.ResumeLayout();
table.Size = reportControl.Panel2.ClientSize;
table.PerformLayout();
table.SuspendLayout();
// Add the TableLayoutPanel to the main form here
Shouldn't that be enough? Unless I am very much mistaken, I do not touch the TableLayoutPanel between this code block and when it is added to the main form. Still, when it is first added, it looks way different than the second time. Oh, and the TableLayoutPanel is double buffered, so that's not it I think.
The extra thing that happens when you call Controls.Add() is that the native Windows window gets created. Plus the windows for all the controls you put in the panel. Which tends to be slow because TLP is often stuffed to the gills with controls. This doesn't happen when you Remove() the control and don't Dispose() it.
You can create the window early by calling CreateControl(). It will take just as long, but maybe isn't as noticeable.

C# Only refresh PictureBox/Panel when tell them to refresh?

I'm making a bomberman game in a C# windows form application. It has over 300 pictureboxes (walls) that are placed on a panel. The picturebox of bomberman himself is also on that panel.
When the location of bombermans picturebox changes, all the controls on the panel are automatically refreshed. Because there are so many controls on that panel, and because the location of the picturebox changes multiple times per second, the program becomes laggy when I try to move.
I want to have control over the refresh event of the panel (and it's controls), because I think my problem is solved when only the pictureboxes that need to be refreshed, are refreshed programmatically.
I hope someone can help me out with this!
Ruud.
If you move the child, the parent has to be refreshed because it may need to draw the area where child was located previously. It would also mean that all children (of parent) would get refreshed.
OTH, using so many controls may not be a good idea. I would suggest you to keep data structures describing walls and then use it to draw it within Panel (or your custom control). You can write your own logic for hit testing (mouse or keyboard click within wall boundary) by capturing mouse/keyboard events at Panel/Parent level. With correct organization data structure, hit testing can be very efficient.
You are trying to paint the whole form which will surely take time . If you want to change only a part of the form, which in your case is Moving the bomberman to a new position, Only invalidate the area you want to repaint and then pass it to the Invalidate method.
Do something similar to this.
//Invalidate previous position of bomberman
Rectangle invalid = new Rectangle(picturebox1.Location.x,picturebox1.Location.y,picturebox1.Width,picturebox1.Height);
Invalidate(invalid);
//Add code to move your picture box and then call above two lines again
invalid = new Rectangle(picturebox1.Location.x,picturebox1.Location.y,picturebox1.Width,picturebox1.Height);
Invalidate(invalid);
Note sure but somthing similar polished code would work...
Here is a link to an example for reference. http://msdn.microsoft.com/en-us/library/ms229628.aspx

C# resizing issue

I have a form with a TableLayoutPanel docked to it, and with a TextBox, Image, TreeView and ListView within that Panel.
When the user resizes the form, these controls resize with it, but there is a noticeable delay if the user resizes quickly or if the user maximizes the entire form; the delay is so considerable that I was able to screenshot it:
You can also notice that the "Options" button is displayed twice, once where it should be (on the upper right-hand corner) and once in the middle of the search box (where it was before the form resized). This isn't supposed to happen, but is also caused by the delay.
Shortly after this screenshot was taken, the form looked fine, but does anyone know of a way to eliminate or reduce this delay?
I edited the image for privacy reasons, but there were only 60 or so items in the listview.
Do you have any special code handling the redrawing?
If so are you using the BeginUpdate() method and the EndUpdate() method?
From msdn:
Prevents the control from drawing until the EndUpdate method is called.
These methods (depending on your situation) could cause the components not to be updated until after the resize has occurred. This might stop the items appearing twice on the screen and speed up the resize.
Maybe you have virtual items in your listview, and your items are recalculating slowly? Do you have any code that is running when listview need redraw?

Categories