C# Main form refresh with dynamic controls - c#

I'm developing a windows form application with controls on the main form that retreive their values from a mySQL database. When the database gets updated I need the form to repaint and refresh the controls. Can anyone reccommend a solution to this? On sub forms I've instantiated a new instance of the form and dispose of the old one, but I can't do that with the main form. Thank-You for considering my question.

I'm not sure if correctly understood your question, but you could put your controls inside of a user control and use-it in the main form. Then, you could do the same you did with the forms: dispose and create a new one.
This should solve your problem, however, you may have some problems with scrollbars and the resizing of your form.

If it were me, I wouldn't dispose of a UI with another, that is in focus for the user. That would kind of irritate the user especially if the update is automatic.
Suppose you have view-only controls like gridview or labels updating with live values, then you can put a time interval and display a seconds ticker clearly telling the user when an update is going to happen.
You should consider having an update method on all your controls (or one usercontrol having all the controls) which you can trigger to update the controls at timed intervals.

Related

A process on a single win form window

I am developing an application in Windows Form C#, it begins with an explanatory window, language selection and a start button when the desired language is selected, I want that when I press the start button, all the elements disappear and begin the application process, I had thought of creating a new form, but this opens a new window and I don't want that, I want everything to happen on a window. Apart from making all the previous controls invisible, is there any way to achieve this? Or maybe a way to make all the controls invisible without going one by one?
You could put multiple controls in a panel for example and hide/show entire panel.
If you dont want to do that, you could always do it in a loop
for example:
foreach ( var control in this.Controls)
{
control.Visible=false;
}
Ofcourse you could also add controls dynamically, but that might be hard for a beginner.
You could also make use of MDI forms, but that might be also not worth it.
SOLVED
Solved using user controls, user controls allow me to design the application interface in the same way as a form and I can add and remove that control from the form as many times as I want, making it possible to display numerous interfaces in a single Windows Forms window.
This solution was suggested by Jeroen van Langen in the comments of my question and it was exactly what I was looking for.

How do I know that a MDI child form has visually changed?

I have MDI WinForms application written in C#. Normally only one MDI child form is visible and all others are in background. Child forms content may occasionally change in background (for example, web browser control may be displaying a page that is dynamically changing every N seconds, chart controls are being filled with data as time goes on).
I want to show small previews of child forms when user hovers a mouse over or clicks on a special button in a toolbar of the main form. I can successfully use PrintWindow function as described here to make screenshots of child MDI forms. This works even for non-active child forms. The only problem is that taking every screenshot may take significant time (about 100-120 ms), probably because of the complex structure of the forms, so that if I make screenshots right before I want to show the previews then this creates a noticeable delay, especially when there are a lot of child forms (e.g. 10-15).
I want to optimize this and re-create screenshots only when it is really needed. Here is what I mean. Initially would I create screenshots for all the forms, store them in a "cache" and show previews. Later, when I need to create previews again, I would like to determine somehow that visual content of MDI form has changed (or change is pending) and re-create the screenshot only in that case, and otherwise use "cached" screenshot.
I tried to implement this by overriding of WndProc function of the child form class and looking for some messages like WM_PAINT or WM_SETREDRAW. But when I log all messages I see neither WM_PAINT nor WM_SETREDRAW even while the form is active (in foreground) and the web browser control on it constantly updates its page. Probably those event are sent directly to the controls of the form, but not to the form itself.
I don't want to traverse every form and connect to "changed" events of all the controls, because all of them are very different and not all have such notification events.
I guess that every control when it wants to change its visual representation sends some notification to OS to force self repaint. So, is there any way to detect such notification from any control inside MDI child form?
UPDATE:
I found WinAPI GetUpdateRect function that should return a rectangle that needs to be redrawn. I thought that if it returned non-empty rectangle then that would mean the screenshot needs to be updated. I tried to call it before the call to PrintWindow, but it always returns empty rectangle.

Concurrent data loading with winforms

So my problem is this. I have a form with a panel in it. This panel serves as the container for multple different usercontrols, of which only one is visible at a time. Some of said usercontrols display a lot of data from the DB, so loading them takes a little bit of time (the data is shown in a bound datagridview). I tried creating a LoadData-method for these controls that I then launch in separate threads and once they've done their work, they enable the actual buttons on the main form for displaying them.
There were, however, many different problems. First, I can't call this.Invoke on the usercontrol until its handle is created, which seems quite hard to force, especially if I want to show a splash screen during the initialization (the main form's handle isnt created yet).
I did manage to force this by setting the form.Visible = true and then calling form.CreateControl followed by form.visible = false. This does, however, show the form blinking on the screen which doesn't look nice.
I also tried not using Invoke if the handle is not yet created, but this brings me to the problem of my data object being created in a different thread and then not being accessible for the control's "normal" thread.
So as is probably quite obvious, I'm quite lost when it comes to multithreading, especially so with winforms, and even more so at the launch of the application. My explanation might also be rather confusing, but I'll try and clarify if it's needed.
So what is the correct way of doing this?
Hard to know where to start with this.
Can't figure out whether your problems are premature optimistion, or trying to retro fit multi-threading.
If I had say a six buttons and one panel and the buttons flipped a usercontrol in the panel to visible, My thread would return a user control, which I'd then add to the panel and then enable it's related button.
Takes all the synchronisation stuff right out of the equation, and gives you maximum scope for optimistion the getting and setting up of the controls.
Or you could setup all the user controls but not bind them and get your threads to bind on completion, I prefer the former way though, a bit more abstraction and you could get to define a view, mark it up with some useful attribute and just get you main form to kick off a process which would "just do it".

How to improve the loading time of winform?

I have a WinForms application. the main form is has a lot of controls and that is one of the reasons that makes it load very slow. what I would like to do is to make the form load faster.
I have set the beginupdate and endupdate. The form is not being rendered in the background worker thread, because this is the main form. There are no initial forms. When the user clicks the application icon, this is the first form that loads up. Adding a progress bar or any splash form is not a good idea for me.
I have checked other questions here on Stack overflow but they do not seem to face the same problem as I do.
If there are some examples/ideas you have in mind, it would be nice of you if you can share it with me.
A few suggestions:
Try to minimise the complexity of your UI. Your users will thank you and you'll have fewer controls to load. For example, if you have 3 or 4 controls that are not used often, can you move them into a dialog or fold-out "advanced" section of your form, so you can defer creating/showing them? Are all the controls needed? Really? Think about the workflow you are trying to achieve - is the current set of controls the simplest way to achieve the workflow? DO all the controls need to be shown at once? Perhaps you could place them on to separate tabs in a tab control (and thus only actuallyl create the controls as the tab is shown)?
Can you reduce the range of control types used? Each new type of control may cause your program to load up a new dll to support it. Every dll that has to be initialised causes extra startup time.
Are you using any controls that are slow to start up? A simple text field will be fast, but a complex graphing control may be slow.
How many assemblies (of your own) are loaded? Combine all the code into a single assembly (e.g. with ILMerge) and load times will probably improve quite a bit.
Remove any initialisation code that isn't needed. Can you simplify the initialisation? Can any initialisation be deferred (e.g. only create some member variables when the user clicks on the first button that actually needs that data to be present, Don't try to create a connection to a database if it's not actually needed yet, etc)
Can you defer creation of (some of) the UI? For example, you may be able to place a group of controls into a separate UserControl form, and then add this form programmatically to your MainForm shortly after startup (e.g. on a Timer). This will allow your MainForm to appear very quickly, and then be "populated" shortly after with additional controls, which may not improve the actual startup time, but it will "feel" a lot faster and more responsive to start up. (This approach can also be extremely effective if your MainForm scrolls and those extra controls are initially not on-screen, as they only need to be created if the user scrolls down enough to see them)
Are you displaying any information that might be slow to load (e.g. large bitmap images or data fetched from an SQL server)? Can you defer the loading of them or run it as a background thread? Use compression to speed up loading? Reduce their resolution to minimise the amount of data that must be loaded? Pre-process data and store it in a quick-start cache for the next time the program is run?
Can some controls be replaced by an optimised approach? e.g. You can create a "button bar" as a set of 10 separate controls, or as a single control that draws iself with the appearance of 10 buttons. It's much easier to make the single control initialise and redraw faster than 10 separate controls.
And of course, once the most obvious low-hanging fruit has been collected (or even before):
Run the program under a profiler and see where it's spending its time.
Try to minimize the code that executes during on load of main form or any of the control that is placed on the main form.
You can also explore NGEN which is Microsoft's tool which helps in improving managed app's performance
When a form loads it initializes all its controls.
The Form itself isn't taking you a long time.. It's your controls.
Go over your controls and check what can be improved in their constructors and initializers.
Do you need all of the controls immediately? If not perhaps you could load them programmatically after some event fires that lets you know you need that control.
If you have several controls to a parent control, call the SuspendLayout method before initializing the controls to be added.
After adding the controls to the parent control, call the ResumeLayout method. This will increase the performance of applications with many controls.
For example:
private void LoadData()
{
// Suspend the form layout and load the data
this.SuspendLayout();
LoadMyData(); // logic to load your data will be here
this.ResumeLayout();
}
EXPLANATION:
SuspendLayout() - Stops the layout object from being updated and thus the component does not spend any time making calculations for repainting until the layout is resumed.
ResumeLayout() - Recomputes the layout once after all of your changes are made, resulting improvement in performance.
Why use SuspendLayout() and ResumeLayout()
It prevents layout accidents when controls have layout properties that affect each other.
It adjusts multiple layout-related properties like Dock, Auto-Size etc.

c# User Control Navigation

I am making a c# windows app that has one MainForm and many User Controls (LoginPage, HomePage, MyListPage, etc.) embedded inside it. I am using Visual Studio 2005 to design the GUI.
In MainForm's constructor I do:
Controls.Add(new LoginPage());
Controls.Add(new HomePage());
Controls.Add(new MyListPage());
...
LoginPage.show();
But I have over 30 pages that I add to MainForm's constructor and I think this is the culprit of my app's lag at its runtime. Does anybody know a more standardized way of using User Controls for a one-form navigation app?
I'm assuming you have a way of navigating between pages - your user controls aren't all shown at once?
If that's the case, you should be able to do the following:
Create one of the user controls on construction to use as the initial page.
When the user performs an action which means your app should move to another page, remove the current user control from the form, dispose of it, create a new one of the required type, and add it to the form.
If you only want to create each user control once, you can use a caching mechanism so that each one is only created once (and don't dispose of the controls as you remove them).
If you use this approach, it should get rid of some of the initial lag, and trade it for multiple smaller lags as the user navigates to each user control for the first time.

Categories

Resources