I currently have a form which I am using. When a user presses export button, it exports some data to an excel worksheet. I have the process happening in the background and it doesn't visually show the user the excel worksheet while writing but does after.
On the c# form, when they click to export, I disable the form so that they cannot press anything on it. I would like there to be a message box or some sort of toast/indication that the excel is writing, and when the excel is finished, the message box/toast/indicator to close and allowing the user to continue.
At the moment the form is disabled, the excel written to, the form is then re-enabled. I have a message box appear using MessageBox.Show("text"); but it isn't really that elegant and looks shoddy.
Has anyone done anything similar and could point me into the right direction.
Thanks,
J
You could add something like a StatusBar to the bottom of your form instead of the MessageBox. When the export begins, you can show the information on a label on that statusbar and remove it, when the export finishes. Additionally you can add a progressbar to that statusbar which indicates the status of the export progress.
I assume that the process that you are running is on the user interface Thread and not a separate Process (a separate application)?
You should follow up like this. First you show the MessageBox or another dialog (you can use a form of your own design). Then you can use a BackgroundWorker class / Thread to initialize the time consuming work. This way the UI thread will not be blocked. Finally when the work is done, you close the dialog.
If you do not know how long it will take, use a wait / progress spinner, maybe in combination with a row counter that bumps up for each row or batch of 1000 rows depending in volumes. This way the user can see that it has not hung and should hopefully patiently wait for it to complete.
See this post: wpf loading spinner
Thanks for all your help,
I managed to work thous out myself in the end using a progress bar on win forms which increments as it writes to excel through my system, the current row in excel it writes to is the value on the progress bar, once its finished, the bar is full and I hide the bar :)
J
Related
I have 2 windows. The main form and the Loading form. In the main form you send a request which will be executed. Because this takes some time, I made the Loading-form with a progress bar so that the user knows the program is working.
What I want to: The Loading-form should open itself when the process ist started and close itself when it's finished.
At the moment I have code that looks something like this:
Loading.Show();
Loading.MakeAStep(); //used for progressing the progress bar
//program is working
//finishes
Loading.Visible = false;
Loading.ResetProgress(); //Sets the value of the progress bar to 0
My problem is: The window with the progress bar opens, but there is also a label which shows "please wait". When the form opens, the progress bar works perfectly, but the label is just a hole (it really is you can look through it). When I use instead of visible = false form.Close, it works just fine with the label but I get an error when I try to start a progress in the same session.
What I want/need: Either a solution to the hole-problem, or an effective way to open and close a form several times during one session.
(Posted the solution on behalf of the question author).
The answer is in the comments: The UI blocks and I needed to Update the form with Loading.Update(); I put that between Show and MakeAStep.
As already mentioned by others, the problem is that you run your long running process in the UI thread. To avoid this, you should improve how the loading form receives the task and works on it:
The loading form should get the thing to run as a Task (maybe by a method Run(Task task). After getting this task the loading form can attach another action to it, what shall happen when the task is finished by using .ContinueWith() and simply closes itself when it reaches that point. After that it will Start() the task and call ShowDialog() on itself.
In my form_load I have a mysql connection that loads data in a datagrid, when starting my application it will first try to load the mysql database and after its done it will load the form/interface with all the controls.
This leaves the user the impression nothing is happening, how can I first load the form/interface with all the controls and then my mysql database?
I would say, 3 approaches
1 - Separate Splash screen
2 - On-Form "splash screen" - first thing you do on form.load, is Me.Show(), then show a message, something like "Please wait while data is loaded". Progress can be shown to users as well using Application.DoEvents which will refresh your screen.
3 - Background worker thread. Using it, you can actually give user progress updates. That will leave your form completely responsive. http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx
Move your code to Shown event or OnShown overridden method. this will allow your form shown to user before it loads grid.
You should move your "Database calls" to worker threads as well.
protected override void OnShown(EventArgs e)
{
//Delegate the DB calls to worker threads here
//everything will be smooth then..
base.OnShown(e);
}
There are two ways to approach this situation. You need to pick the approach that best suits your needs.
Approach 1: Create a splash screen. A splash screen is a small window that opens up and usually had product info and a message like "Initializing...". You can see this in a lot of applications, such as Microsoft Office. You can see how to make one by looking at this article.
Approach 2: You will need to make your load data happen in a separate thread then your UI. You will need to load your data in the separate thread and bind it to a list of some sort temporarily, then after its done, bind the list to your Datagrid
Use other thread for loading data from mysql. It's loading form first, but not displaying it until code has finished work.
new Thread(new ThreadStart(LoadDataMethodHere)).Start();
You can use Form Shown event.
Alternatively you can use a different thread to connect to database and show data or use a timer.
I have an Excel Add-In that pops up a form. If the user fills in some values and clicks the "Apply" button, the values are correctly sent to the underlying worksheet and the pop-up form closes. If, however, the user clicks on "Cancel," a Messagebox pops-up verifying that the user wants to cancel. Clicking "Yes" causes the pop-up form to close, but also sends Excel behind the previously active window -- very much like pressing Alt-Tab. This is not good!
Does anybody have any notions about how to keep Excel on top?
Thanks!
Randy
You could put this in right after the message box ActiveWindow.ActivatePrevious
And test with
Debug.Print ActiveWindow.Caption
ActiveWindow.ActivatePrevious
Debug.Print ActiveWindow.Caption
I looked for all sorts of variations on ActiveWindow/ActiveView but couldn't find anything applicable. Finally I went around the Mulberry bush to come up with this:
IntPtr excelWindow = excelWindow = SpreadsheetApplicationFactoryBase.TheExcelApp.ExcelWin32Window.Handle;
Win32.SetActiveWindow(excelWindow);
Ugly, but it works. The factory is a small class that creates/returns the Excel instance.
I very much appreciate the input.
Randy
I have a WinForms application that, at some point, will do some calculations that take a couple of seconds. During this time, I disable the controls. Additionally I want to display a popup that kind of 'blocks' the application more visibly.
I tried placing a Panel on top of the Form in order to do so, but there I'm somehow not able to add any text to it. I.e. the Labels and ImageBoxes I put there are somehow not displayed or behind the Panel.
Any suggestions how I could achieve this in a quick and easy way? .. I mean, without redesigning the whole Form.
Your problem with the things not showing up in your additional panel is that everything is happening in the same thread, but your calculations are blocking everything from appearing because they are hogging up the thread. You should look into using a backgroundWorker, which is one of the tools in WinForms. You should throw the function call that performs the calculations into the DoWork method of the backgroundWorker, then the form itself can continue to function during the calculations.
See http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx for examples
Create a Dialog Box (windows form) to popup during the processing, then you can have the Dialog Box close once your processing is completed.
By using a Dialog Box not a Message Box, you can still have control over closing the window when your processing is done.
You could create a simple UserControl with just a Label and an ImageBox, maybe with public setter for their values. You can add it to your form setting its Visible property to false. Then you can make it visible during your calculations and go back top invisible in the end.
I am coding a system which has a small FTP module included inside, it's not the main feature at all, but needed...
I must link the progressbar with the WebClient class event DownloadProgressChangedEventHandler and AsyncCompletedEventHandler, the progressbar increment is ok, and the ASyncCompletedEventHandler launch a MessageBox (as intended), the problem is that the progress bar see to load too slow...
problem :
My MessageBox pop at 100% (launched by the event handler), BUT when the MessageBox pop my progress bar is only at +-80% (but the .VALUE is really 100), the first though I had was that they have added a "smooth" effect in Windows Vista which slow down the progressbar relatively to it's true value.
If any of you have experienced the same problem thanks for your help.
For those of you who want to know, Vista actually add a "smoothing" to the loadingbar change, it look like the "Tweening effect" of Flash.
I tried on Windows XP and the bar reach 100% exactly when the value reach 100. On Vista it look like they have decided that the "loading" would be splitted over a delay X.
Before you display your message box, call Application.DoEvents() to force all the pending Windows queued messages to be processed. Your progress bar is probably not getting a chance to paint itself one last time before the message box displays.
Why not simply set the progress bar value to 100% on the same DownloadProgressChangedEventHandler event handler that displays the message box?