System.InvalidOperationException when managing a dialog - c#

I have encountered an error called System.InvalidOperationException.
Additional information: Specified element is already the logical child of another element. Disconnect it first.
I have searched through internet for the solutions but none of them solve my problem.
I created a button called "Open Dialog", to open a dialog. After I opened the dialog, there are two buttons showed in the dialog, "Save" and "Cancel". The function of "Cancel" is to close the dialog. However, after I clicked "Cancel", when I tried to reopen the dialog again by clicking the "Open Dialog", I have encountered the error stated above.
I will post my codes here as well for the event handling method.
In the class of MainWindow:
private void openDialogButton_Click(object sender, RoutedEventArgs e)
{
PersonIDTable.ShowDialog();
}
In the ViewModel:
public void ShowDialog()
{
PersonID.UserControls.PersonIDDialog dialog = new PersonID.UserControls.PersonIDDialog (this);
dialog.Show();
}
In the class of Dialog:
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
Do you guys have any idea to solve the problem? Your help will be much appreciated.

You pretty much told the answer in your question, you closed the dialog so you can't reopen it.
Insert the creation of PersonIDTable inside openDialogButton_Click, that should fix it.
Example:
Form1 form = new Form1();
form.ShowDialog();
Would have told you this through the comment, but I don't have enough reputation.

Related

Open and close forms through a menu c#

I've had a look around but none of the answers make any sense to me. I have a menu form which has buttons on; when users come to use the menu form, you can open other forms from the menu. Currently, I can get the form to open, but the menu form stays open too.
private void BtnAddNewCar_Click(object sender, EventArgs e)
{
AddCompanyCar carForm = new AddCompanyCar();
carForm.ShowDialog();
}
The code above opens the form AddCompanyCar from the menu. How do I add to this code so that the form 'Menu' closes when AddCompanyCar opens?
Are you sure want to do this as it impacts usability. If you're using WinForms, then just create a container window, and replace the panels instead. Might be easy and best way
If not and you wanna go-ahead, can take a look on this example
Why not just hide it, then show it again when ShowDialog() returns?
private void BtnAddNewCar_Click(object sender, EventArgs e)
{
this.Visible = false;
AddCompanyCar carForm = new AddCompanyCar();
carForm.ShowDialog(); // execution stops here until "carForm" is dismissed
this.Visible = true;
}
by closing the main window, you destroy the context in which you were previously working. As others suggest, simply hide the main window so you can return to it.

Close event not working

I want if user click the close button to close a WinForm, it will perform some work such as showing MessageBox message:
void frmMemberSearch_FormClosing(object sender, FormClosingEventArgs e)
{
MessageBox.Show("close message");
}
the about code does not work. Does anyone know what may be the problem?
just double click form closing event on Form Properties Tab.

Properly Closing Secondary Form VS Application Exit

This is probably going to be a standard question. I have read lots of articles on this but none point out the issue i am having specifically.
I am developing a WinForm and have a "Main Menu" form that is loaded on startup. Within this main are several buttons which open up individual modules (other forms) of the program.
I can open up the form no problem and can close it and re-show the main form no problem. The problem lies when a user hits the (X) in the control box, the application doesnt exit because the main form is still there, but hidden. I know that i could put an application.exit() in the close event of the form. However, then if i have a button that closes the form and wants to unhide the main form, the application will close due to the formclosing event.
Can someone help me understand this principle. I dont think it should be as hard as it seems to me and i dont really want to use Panels.
Thanks in advance.
-Joseph
the following code solved the issue based on the answer provided below
private void btnHome_Click(object sender, EventArgs e)
{
Form f1 = Application.OpenForms[0];
f1.Visible=true;
this.Close();
}
private void frmCostControlMain_FormClosed(object sender, FormClosedEventArgs e)
{
Form f = Application.OpenForms[0]; // The main form
if (f.Visible==true)
{
f.BringToFront();
}
else
{
Application.Exit();
}
}
You can check the Application.OpenForms and see whether some non-hidden forms other than the current form are around. If you only want to check the main form, you can check Application.OpenForms[0]. Since it was opened first, it will always be at index 0. From memory:
Form_Closed(object sender, EventArgs e)
{
Form f = Application.OpenForms[0]; // The main form
if (f.Visible) {
f.BringToFront();
} else {
Application.Exit();
}
}
When the close button is clicked you would first unhide the main form and then close the current form.
I still don't understand your question, but I guess you could use the
Application.Exit().
You should then check the arguments of your FormClosed event.
The Close reason is as follows:
Click on [X]:
CloseReason = UserClosing
Application Exit:
CloseReason = ApplicationExitCall
You could then handle it properly
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (e.CloseReason == CloseReason.ApplicationExitCall)
{
//Application.Exit();
}
else if (e.CloseReason == CloseReason.UserClosing)
{
//[X] was pressed
}
else
{
//Many other reasons
}
}
I guess there is a much cleaner way of handling your problem. If you provide a bit more details, I think someone would be able to help you along.

FolderBrowserDialog not showing up on second form

Ok, this is the main essence of what I am trying to achieve and the symptoms of what it is doing.
I have a main windows form. On this form the user can click on a button that will open up a new and seperate form. This form will have a button that is supposed to display a FolderBrowserDialog. Instead it simply locks up form2 and never displays anything.
Here is essentially the code I have dealing with the form etc.
This is in the first form that is loaded after i do some uninteresting things.
FORM1.cs
//do stuff
//In a button.click method I do the following
Application.Run(new Form2(myParameters1, 2, 3));
This is the second form that is called from the first form
FORM2.cs
//do more stuff with the parameters on load
//user clicks on a button
private void button1_Click(object sender, EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
fbd.RootFolder = Environment.SpecialFolder.Desktop;
fbd.Description = "This is the browser dialog box";
if(fbd.ShowDialog() == DialogResult.OK)
{
//do stuff
}
}
After I click on the button the dialog box does not show up and the form2 gets locked from doing anything.
I have also attempted changing the
fbd.ShowDialog()
To
fbd.ShowDialog(Form2.ActiveForm)
with the same results.
Any help would be appreciated! If you need more info let me know and I can try to provide all that I can.
EDIT
I forgot to mention (and actually completely forgot) That the method that opens up the second form is a seperate thread.
So the first form starts a thread, which opens the second form, which is supposed to open a dialog which it is not. Now i think it has to do with the threading..
I have figured out my issue. It ended up being that the thread from Form1 that was opening Form2 was not able to open DialogBoxes because it was seperate from the UI thread entirely.
I ended up working around using that thread and just eliminated it completely which solved my problem. The dialog box opened up just as I wanted.
Thank you all for the responses though! They did help me figure out a few other things I failed to do correctly.
I had similar problem. Main GUI thread was creating a backgroundworker thread to write to database but when background thread is failed used to show a custom control dialog to save exception file. THis custom dialog was shown correctly however Browse button on it to open folderBrowserDialog to save the exception file wouldn't show. My custom control would show "Not Responding" in its title bar.
What I did was instead of calling Custom Control directly I made it call on UI thread itself
like this.
void DBThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
this.Invoke(new CrossThreadExceptionHandler(CatchInterThreadException), e.Error);
}
}

How Can I open a Winform Dialog when closing another?

I have a Dialog with showing some information about an object. I want to close this Dialog to show the same dialog but now with the object's sibling. It is a complex dialog that loads different components depending on the object assigned, I cant just change the reference to another object
I tried launching the new one in the Closed event, but the former hasn't disapear from the screen and keeps showing. Also tried a static method that is called whithin the Dialog, passing the same Dialog as a parameter, so it close the dialog 'dialog.Close()' and opens a new one with the new object to show. But still the former one keeps opened behind.
Is there a way to accomplish that, closing the first window and opening the second?
( THIS IS The Static approach, the window passed by parameter doesn't close until the new one created is closed)
// From the Dialog try to launch the second one closing this.
private void btnSibling_Click(object sender, EventArgs e)
{
SwitchToSibling(this);
}
private static void SwitchToSibling(SiblingDialog window)
{
try
{
double id = 0;
id = window.SelectedSibling();
if (id != 0)
{
// Get's the same Parent so to the new Dialog
Control owner = window.Owner;
window.Close();
Sibling sibling= Sibling.Get(id);
SiblingDialog.ShowSibling(sibling, false, owner);
}
}
catch (GroupException ex)
{
MessageBox.Show(ex.Message);
}
}
I had the same problem, and after a lot of troubleshooting I managed to solve it in an entirely different way: I first wait for the Forms.Application.LeaveThreadModal event to occur, and then I wait for the next Forms.Application.Idle event to occur. By that time the first dialog has completely disappeared, so it is possible to launch the second dialog without any problems.
Waiting only for the idle event, or only for leave-thread-modal event, or for both events in the opposite order, will not work.
CAUTION: Waiting only for the idle event APPEARS to work, but only for as long as the activation of the second dialog is done by clicking a button of the first dialog with the mouse. If you trigger the button by pressing the mnemonic key of that button on the keyboard, the second dialog appears above the first dialog! You have to go through the sequence I described in order to avoid this!
After thinking about it a bit more, it seems to me that my solution is kind of "magic", which means that it may stop working in a future release of the dotnet framework, so I think I will ditch it and follow the advice of Mike Hoffer, which, as far as I can tell, is essentially the same as the answer that jmayor gave for himself and marked as accepted. (The truth is that Mike Hoffer's answer is a bit hard to follow.)
Without knowing the specifics inside the Sibling and SiblingDialog classes, sure you can. The only constraint would be that if you close the window that is the application's main window, the application will exit.
You could, for instance, provide a method like so:
private static void CloseAndShow(Form formToClose, Form formToShow)
{
formToClose.Close();
formToShow.Show();
}
That would close formToClose and show formToShow.
If you've set the owner for the first dialog, and you know its type, you should be able to solve this problem as follows:
Write a custom event on the dialog's
owner.
When the user clicks the close
button, invoke the event.
Do not
close the dialog from the button.
Have the owning window close the
dialog when the event handler is
invoked. Then have the owning dialog
show the sibling dialog.
An extension of Fredrik Mork's answer, that addresses the fact the closing form may be the form controlling the exit status of the program.
private static void CloseAndShow(Form formToClose, Form formToShow)
{
Application.Run(formToShow);
formToClose.Close();
formToShow.Show();
}
Application.Run tells the program to exit when the form passed to it closes
As it seems that you are setting the owner of the dialog, you can try to use owner.BeginInvoke() in the FormClosed() event handler in MyForm class. :
public partial class MyForm : Form
{
static int count = 0;
public MyForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
public static void ShowMyDialog(MyForm form, IWin32Window owner)
{
count++;
form.Text = "My ID: " + count;
form.ShowDialog(owner);
}
delegate void MyDel(MyForm form, IWin32Window owner);
private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
{
MyDel del = ShowMyDialog;
MyForm mySecondForm = new MyForm();
this.Owner.BeginInvoke(del, mySecondForm, this.Owner);
}
}
The only way I Could find a way around is by calling my dialog from a static method( using sort of a singleton Pattern) , then using a static variable to flag when the Dialog needs to be reopened. So when a dialog execution is ended inside the static method it checks if it needs to be reopened.
Otherwise I don't see a possible way.

Categories