Displaying child form immediately after MDI form is completely displayed - c#

I've MDI winform with a top panel displaying picture and a navigation menu populated from a database on the left. I wanted to display a default child form immediately after the MDI form is displayed. I've used DevExpress WaitForm before displaying everything. However, the top panel remains blank until the child form is completely displayed. What can I do to display the child form after every component of the MDI is displayed. I tried threads but didn't figure out how to properly manage it. Your help is highly appreciated.
Thanks

The child form contains a xtraReport control that generates reports from the database
Sounds like your child form is blocking the main window with its fetching of database data and report generation.
Consider using another thread to fetch the data from the database. Once you have all the data, have the UI thread set the data source property (or equivalent) on the xtraReport control.
For threading you could use:
An explicit Thread (not recommended)
A Task though you may need to thread-marshal to your UI thread
An async method that you can await (recommended). This makes it much easier to do the work on another thread then automatically marshal the results to your UI thread where you can update xtraReport

Related

Flicker of Mouse in TextBox , Graph while Processing Large Data in other UI Control

My Application processes large data Entries and display each group of entries in Tree List View.
The Main Form has other Controls such as Text Box "Used as Filter for Entries" and Graph "Displays Entries Data"
Every thing work Great , The Problem is while Processing Data entries and Displaying on TreeListView if i places the Mouse on textbox or graph , it keeps flickering and blinking ! , i can write data successfully to textbox but it is always flickering.
Take into consideration that The function of handling that large data entries and display on TreeListView is in separate thread.
so what is the problem here ? and how this separate thread affects rest of other controls in my mainform ?
One solution: Make everything Visible = false until your processing finish up, then Visible = true. You can also display a message "Please wait" while the items are hidden.
Another solution: avoid on-ui-thread long operations. Avoid fast add/delete into listview or treeview. It is better to clear everything then add everything. Yo can also hide your treeview, add items to it, then show it.

Handling Detail updates in Master-Detail view in Winform C#

I have an application which has a Mainform that has 2 panels using a splitter. The top panel is a form that has the binding navigator, dataset, bindingsource, tableadapters..
The bottom panel is a form as well. It's just a datagridview basically. I pass the bindingsource from the top form, into the bottom form when the Mainform loads.
The bottom form takes the bindingsource, and uses a relationship (between two tables) for it's own datasource member.
Viewing the data works great.
When I update data in the master, i capture it when the user is navigating off the record. I use bindingsource.EndEdit(), DataSet.HasChanges() to verify and then tableadapter.update to write the data before navigating to the next record.
That also works great.
Now, how do I capture and write data in the detail(bottom) form? all it has is the bindingsource passed in.
I have a partially working solution, where the top form actually uses a second tableadapter.update statement to write the the child table.. but it seems to take 2 record navigations for that to work. (at which point the data is actually updated correctly though)
Any high level better ways to work all this?
thanks
R
Looks like it was either a general issue with the event orders.. or maybe it's specific to the bindingnavigator or my setup.. but in order to get the bottom form's events firing BEFORE the record is changed in the top applet (when clicking directly from a modified grid row in the bottom, to the navigator), i had to explicitly move focus first in that top applet event. In my case, i trapped any click on the navigator and just ran this.focus(); that caused all the bottom form events to fire before continuing on. This then allowed my haschanges() check in the top form to happen after the bindingsource.endedit in the bottom form.

App window hangs while DataSource loads

I press a button (located on the main form , the MDI Parent) which triggers a BackgroundWorker's RunWorkerAsync method (located on the same MDI Parent form). In this method I set the DataSource of my DataGridView which is located inside one child window owned by my main Mdi Window. Here's the code for the RunWorkerAsync:
Action d = () => {
((DataGridView) data_viewer.gridviewer).SuspendLayout();
((DataGridView) data_viewer.gridviewer).DataSource = datatable_copied;
((DataGridView) data_viewer.gridviewer).ResumeLayout();
};
base.Invoke( d );
The above code populates the grid OK. All data is delivered into the grid. The problem is that I will work with very big tables and while the data is loaded the whole app hangs, including the Mdi Parent window. I wouldn't mind having the DGV hang but for the Main MDI parent and the child window containing the DGV to hang while this whole thing loads is too much. How can I solve this? I want to be able to move the child window containing the DGV without a problem while it loads (or maybe draws) the whole datatable. I thought using a background worker would solve the issue but apparently it doesn't.
There is no getting around rendering a huge table on a WinForm.
Whether it is async or not, the UI still has to render the entire grid. Pushing it to the background thread just makes the UI more responsive while it is being computed and rendered.
Another approach is to page the data meaningfully, so that you:
Reduce the network traffic
Reduce memory of the WinForm
Speed up the rendering time
Is a user going to need 1,000's or 100,000 rows of data in one hit? Humans can't compute information on that scale - hence reporting aggregates the values.
Have a look at this StackOverflow post relating to paging a DataGridView and see if that helps.

Not sure on class design

i originally had a main form with 2 panels, one had a graph in that i clicked on the other had the results displayed related to what you clicked.
All this code was dumped in the main form.
I tried to be a smart alec and use inheritance, so now i have a main form which has a graph objet and i have a superclass graph -> subclass specific graph heirarchy
however now when the graph is displayed in the main form, how do i get the data back to display in the other panel? The reason i ask this is now that the graph stuff is in its own heirarchy, it has no knowledge of the panel on the main form so i have no hwere to set the data when it is set
i hope someone can help
thanks
edit: i think i might just pass the control collection for the panel in to my graph class so i can add the relevant items in there
Depending on the relation between the two forms, you can use events to message data between them.
A click event handeled in the graph can raise an event with the data you need to display, which would end up on the owning form. Depending on the relationship, you either call a function on the 2nd form to display the data, or raise an event to which the 2nd form subscribed to send over the data.
[Edit]
I read Forms instead of Panels.
The main idea remains the same though. From your style of writing, it looks like you have an Objective C history. I know on the Mac, these things would be done in Interface Builder, setting bindings to make this stuff happen, but in the .NET Winforms you do these things in code (handeling events, calling methods, etc). If you like to stick more to the way it's done with Interface Builder, you might want to take a look at WPF applications; bindings work in a very similar way to how it's done on the Mac.
I would design this as an object that aggregates another object. Have a look at the way master-detail view works.

How to draw a control, without drawing the control

I've got a list of UserControl objects; when a menu option is clicked to go to another section of the application it does the following:
Set the currently displayed usercontrol to visible
Clear the main panel's Controls list
New up the requested control (if not already created in the list)
Add the new control to the main panels' Controls list
Dock the new control to fill
Set the new control to visible
I did this because, previously all of the areas of the application were not user controls and they were just collections of controls in a TabControl. The underlying code was monstrous (the code in frmMain was 13000+ lines).
It works well. All controls (what each tab page would have been before) manage their own behaviour, each control has a small code footprint. I can have a sexy menu. All good things.
However, obviously there's a problem. Before, the tabcontrol would load on startup, and all tabs would render (but weren't seen). One tab page in particular has a scheduling control on it and it takes a good 3-4 seconds to draw and adjust its layout. Now that controls are loaded and shown as they're needed, the first time you view this particular control, you see it load and adjust its size/formatting/etc. Which is hardly esthetically pleasing.
My question is, how can I load and render this control so that it'll render and figure out its layout, but without it actually showing the user?
I've tried simple things like:
ScheduleWindow scheduler = new ScheduleWindow() { Visible = false; }
mainPanel.Controls.Add(scheduler);
scheduler.Visible = true;
I've tried creating and loading the control on its own thread (with numerous difficulties) and it still didn't do anything...
Is there any way to achieve what I'm looking for?
Try using the SuspendLayout() and ResumeLayout() methods on the main form? When you call SuspendLayout(), you can do whatever you need to do with the controls you are adding, such as docking, resizing, etc. When you call ResumeLayout(), all changes will be applied at once, and should happen instantaneously.
Alternatively, some controls have a BeginUpdate() and EndUpdate() method, which suspend redraws for that control, allowing you to do heavy work (such as adding thousands of items to a ListView) without seeing the updates happen live. This also improves performance, as rather than redrawing every time the control is changed, you batch changes, then redraw once.
Try calling scheduler.Handle.ToString() and/or scheduler.Refresh().

Categories