Force dialog close in C# - c#

I'm writing a GIS application in C#. A portion of the application allows the user to select a KML file, and then the program will process that file. I'm using an OpenFileDialog, but the problem is that all of the code is executed before the dialog gets closed (and after the user has OK'd the file). It takes quite awhile because the program has to zoom and do other things. Is there a way to close the dialog programmatically before my code is executed?
EDIT: Some code for those who ask.
private void OnKMLFileSet(object sender, CancelEventArgs e)
{
Polygon polygon = KmlToPolygon(openFileDialog2.FileName);
// After this, I no longer need the file, but the dialog stays open until the end of the method
Graphic graphic = new Graphic();
graphic.Geometry = polygon;
textBox1.Text = string.Format("{0:n}", CalculateAreaInSqKilometers(polygon)).Split('.')[0];
textBox2.Text = string.Format("{0:n}", CalculateAreaInSqMiles(polygon)).Split('.')[0];
textBox3.Text = string.Format("{0:n}", CalculateAreaInSqKnots(polygon)).Split('.')[0];
Note polyInfo = new Note("Polygon with nautical area: " + textBox3.Text, polygon);
map.Map.ChildItems.Add(polyInfo);
map.ZoomTo(polygon.GetEnvelope());
}

It sounds like the dialog is actually closed, but it's still "visible" because the main window is busy and hasn't repainted itself yet.
Some ideas:
The easy way: call the Refresh() method on the main form where the dialog is still visible. Always call it immediately after ShowDialog returns.
If loading takes quite a bit of time, it might be desirable to create a pop-up "loading" dialog, possibly with a cancel button. Use the BackgroundWorker class to load the file in a background thread. When the worker is done, the file is loaded and the pop-up window can be closed. Remember not to change anything in the user interface from the background thread without proper synchronization.
EDIT: After looking at the code, I think I see your problem. You're handling the FileOk event. This will have the effect you are trying to avoid. Use the dialog like this:
if (openFileDialog1.ShowDialog() == DialogResult.OK) {
// open file
}
Don't use the FileOk event. I've never had reason to use it before... Also it might be helpful to follow the advice I already gave.

Related

c# custom messageBox show

I need to show up custom messageBox and close it when operation is done.
Problem is messageBox appear normal but without added label wich shows message , i can see only white space...After job is done , messageBox closing work normal.
here is code
public void resetirajSve() {
MyMessageBox poruka = new MyMessageBox();
poruka.Show();
analizaPodataka();
glProstor.Rows.Clear();
poruka.Close();
}
I tried using poruka.ShowDialog() but then code wont to continue executing.. with showDialog method label apper normal...
public partial class MyMessageBox : Form
{
public MyMessageBox()
{
InitializeComponent();
}
}
Some pointers:
1.It seems your custom MessageBox actually inherits a Form. The default MessageBox is rather versatile - see some examples, so there's no need to reinvent the wheel. Focus on more important things.
2.Using ShowDialog() will block all actions from executing on the Form until the newly opened form (you call it MyMessageBox, but it's actually a Form).
3.You could just add a ProgressBar control to display the task's progress and use the wait cursor until it is finished.
4.To avoid the program window becoming unresponsive until the method has finished executing (it can be an issue if it takes a long time), you might want to take a look at asynchronous programming. Here's an example.

C# WinForms ShowDialog() call arbitrary method

I'm working on a console application that creates a form to alert users of some given state - at a later stage, the code base will become a class library.
For now, however, I need to show the form (ShowDialog would be the best method here, I guess) THEN call an arbitrary method before the form closes.
As an example, I need to show the form, set the text value of a label control, wait for n number of seconds, then change the value of the label, then close the form. I know that this sounds a little trivial, but I'm trying to proof-of-concept the design.
I've taken a look around and it doesn't look like this is possible, as ShowDialog() requires me to close the form before I can continue through code listing in the calling method/class.
Here's what I have so far:
PopUpForm myForm = new PopUpForm(string messageToDisplay);
myForm.ShowDialog();
//call myForm.someMethod() here, before the form closes
//dispose of the form, now that we've no use for it
myform.Dispose();
//target method in PopUpform class
public void someMethod()
{
lblText.Text = "Waiting for some reason";
//wait n number of seconds
lblText.Text = "Finished waiting. Form will now close";
//it doesn't matter if the form closes before the user can see this.
}
It looks like ShowDialog() doesn't support this sort of behaviour. I'm looking into BackgroundWorker threads, but was wondering if anyone has any advice on this, or have encountered this before.
If you want to show the form, then continue working, then close it - you can do so via Form.Show() instead of Form.ShowDialog():
using (var myForm = new PopUpForm(messageToDisplay))
{
myForm.Show(); // Show the form
DoWork(); // Do your work...
myForm.Close(); // Close it when you're done...
}
However, if this is purely a console application (and doesn't have a message pump), then this will likely not work properly.
Other options would be to provide a timer within your Form to have it close, or pass a delegate into the Form to run your method on Show, after which it could close itself.
at a later stage, the code base will become a class library.
When you do this, you'll likely want to come up with a different mechanism to provide notifications. Coupling your library to a specific UI technology is a bad idea. It would likely be better to have your library just provide events or other notification, and allow the user to provide the UI/notification to the user.
If this code ie destiend to end up in a code library, I recommend against having it display any forms, ever, of its own volition. The library should generate events, or in some cases exceptions, that can be caught by the invoking application to allow it to display the form. If certain details requiring presentation to the user are internal to the library, expose a DisplayEventData() method from the library.
The ShowDialog-method creates a "modal" window, and usually blocks the UI until you close it (either by clicking OK or Cancel). You would need to create a WinForm yourself, can be a simple one though and create a message-pump for it. You can run your own form by calling
Application.Run(YourForm);
You would need to hold your console-thread with a mutex for example, to keep it from continuing, while the form is open.
The form offers all the methods you know from WinForms like Close, where you could tell your console-thread to continue.
See this on MSDN.

C# WinForms Wait on form to proceed

I'm tired and hungry, so I might of missed it, but from what I can see no existing post covers this...
I'm writing a plugin for an application. My plugin loads a form to get some data specifically, it uses the webcam to scan for a barcode. Once it's found a barcode, the form hides itself (incase it's needed again later). This is how I currently call the form that does the barcode work:
string readData = null;
if (eye == null)
{
System.Windows.Forms.Application.EnableVisualStyles();
eye = new CamView();
}
eye.Show();
if (eye.found)
{
readData = eye.readData;
}
return readData;
So, my problem is that eye.show() doesn't block. It makes the form appear and carries right on before there's a chance for the barcode to appear. I imagine I need to use some form of threading or locking, but my crude attempts to do so have just frozen the interface completely.
The "eye" form is basically just a viewfinder for the webcam, and relies on the camera_OnImageCapture event to make it do it's image checks for the barcode.
Is there an elegant way to make the application calling the plugin wait for the form to finish? Or do I just need to add an accept button to the "eye form?"
Cheers. And humble apologies if this is in anyway a repost.
.ShowDialog();
http://msdn.microsoft.com/en-us/library/c7ykbedk.aspx
"You can use this method to display a modal dialog box in your application. When this method is called, the code following it is not executed until after the dialog box is closed."
You are on the right track. You change the code to show CamView as a modal dialog but do no add an Accept button. Instead change camera_OnImageCapture to close the dialog.

Removing a Control from a Form

So I've got some serious problems with removing a Control from a Form of my application. It's kinda messed up but I can't change anything. I have a form and I have a separated user Control. The control opens an exe file and shows a progress bar while loading it's bytes. And here comes the problem. I do all of it with a BackgroundWorker and when the worker_DoWorkerCompleted method is called the original form should show a MessageBox and remove the Control.
BackGround_Loader bgLoad = new BackGround_Loader();
bgLoad.Location = new Point(this.Width/2 - bgLoad.Width/2, this.Height/2 - bgLoad.Height/2);
this.Controls.Add(bgLoad);
bgLoad.BringToFront();
bgLoad.AddReferences(this.executableFile, this.SourceReader);
bgLoad.occuredEvent();
At first I set the control's location to be in the middle of the Form itself. Then I add the control to the form, and bring it to the front. After these I send the path of the executable and a RichTextBox's reference to this. With the occuredEvent I start the BackgroundWorker itself. And here comes my problem. I should show a MessageBox in the Form when the in the bgLoad the backgroundworker gets to the DoWorkerCompleted status. Kindly I have no idea how to do it. It works just perfect however the control stays in the middle of the form.
UI actions must be performed on the main UI thread. The events that get raised from the background worker thread are (obviously) in a different thread.
You need something like the following code:
private void backgroundWorker_DoWork(object sender, AlbumInfoEventArgs e)
{
// Check with an element on the form whether this is a cross thread call
if (dataGridView.InvokeRequired)
{
dataGridView.Invoke((MethodInvoker)delegate { AddToGrid(e.AlbumInfo); });
}
else
{
AddToGrid(e.AlbumInfo);
}
}
In this case AddToGrid is my method for adding a row to a DataGridView, but in your case it will be a method that does what you need to do.
Similarly for the backgroundWorker_RunWorkerCompleted method
See this MSDN example
I could find a way to solve the problem but I don't really like it. In the addReferences method I pass the Form itself and an object of the bgLoad class. Then in the RunWorkerCompleted I check if the control is on the form and if it is then I remove it.
bgLoad.AddReferences(this, bgLoad, this.executableFile, this.SourceReader);
...
private void worker_DoWorkerCompleted(object sender, DoWorkerEventArgs e) {
if(this.MainForm.Controls.Contains(this.Control) {
this.MainForm.Controls.Remove(this.Control);
}
}
Like this it works but it's awful for me.

C# Forms - dialog form only partially disappears before next action taken

I tried to search for this, but I was not sure how to describe it. If it is a duplicate, please point me to the other question. Thanks.
I created a C# Windows Forms app using VS 2008. From the main form it opens a custom dialog form. When the user closes the dialog form, it does not completely disappear before the application starts into it's next task. The outline of various parts of the form remains until some additional tasks are completed.
This looks very unprofessional and it makes the application appear to be broken, even though everything works great. Is there any way to avoid and/or fix this problem?
FYI, the additional tasks are calculations requested after the form has been closed.
Here is the form closing code.
private void CloseForm_Click(object sender, EventArgs e)
{
Properties.Settings.Default.EndDate = cmbBoxRptDate.SelectedValue.ToString();
rptDate = cmbBoxRptDate.SelectedValue.ToString();
Var1 = cmbBoxVar1.SelectedValue.ToString();
Var2 = cmbBoxVar2.SelectedValue.ToString();
this.Close();
}
Here is the code from the main form that opens the custom modal dialog and then disposes of it after it is closed. I think the dispose might be redundant since the form calls the close method on it's own.
RptSettingsForm RS = new RptSettingsForm();
DialogResult DR = RS.ShowDialog();
String var1 = RS.getVar1().ToString();
String var2 = RS.getVar2().ToString();
String rptDate = RS.getDate().ToString();
RS.Dispose();
Then a connection is established to SQL Server to do some report calculations.
I suspect the last bit is the most important:
Then a connection is established to SQL Server to do some report calculations.
Is that still on the UI thread? If so, that's probably the problem - the repaint event for the main window is probably still waiting to happen, but you're busy with the database.
Fredrik's suggestion of calling Refresh is a good one, but you've still fundamentally got the problem of doing too much on the UI thread. If for whatever reason it takes a long time to establish a connection to SQL Server, your UI will be frozen during that time - you won't be able to move it, resize it etc.
Long-running operations - including just about anything to do with a database - should ideally be done on a different thread. This does make things trickier, without a doubt, but gives a much better UI in the end.
What you can do is to force the calling form to repaint itself after the dialog is closed, before carrying on with other stuff:
RptSettingsForm RS = new RptSettingsForm();
DialogResult DR = RS.ShowDialog();
this.Refresh(); // force repaint
String var1 = RS.getVar1().ToString();
String var2 = RS.getVar2().ToString();
String rptDate = RS.getDate().ToString();
RS.Dispose();
Note that there are two methods that will cause a form (or control) to repaint itself: Invalidate and Refresh. Refresh will force a full repaint immediately. Invalidate will not cause an immediate repaint, but rather invalidate the full control surface so that the full surface will be repainted the next time the control is updated (which may be delayed a bit if the thread is busy with other stuff, as in your case).
To force a repaint after calling Invalidate, you can call the Update method, which will force an immediate repaint of invalidated areas. So it may be, in your case, that you could simply call Update instead of Refresh, since I guess that the areas that were previously covered by the dialog should be invalidated. This might be more efficient that forcing a full repaint:
RptSettingsForm RS = new RptSettingsForm();
DialogResult DR = RS.ShowDialog();
this.Update(); // force repaint of invalidated areas
String var1 = RS.getVar1().ToString();
String var2 = RS.getVar2().ToString();
String rptDate = RS.getDate().ToString();
RS.Dispose();
Looks like your main form is not getting refreshed. can you try calling this.Refresh() after showdialog?

Categories