This may seem like a rather obvious and extremely newcomer question (and it is), but I've merely been attempting to transition between multiple forms in C# Winforms and somehow managed to encounter numerous complications:
To begin, I used the obvious:
frm_hub hub = new frm_hub();
hub.Show();
However, each time this code run, a new instance of frm_hub was created and using hub.Close(); would not work because it was not closing the same new instance of frm_hub
Is a way to close the same instance of a form from a different form - say with a global variable? Or is there some way to integrate a Close(); so the entire program continues to function and new form displays?
As a possible solution to the above issue, I tried to store the same form as a variable:
frm_hub hub = new frm_hub();
private void OpenForm()
{
hub.Show()
}
However the runtime error: 'System.StackOverflowException: 'Exception of type 'System.StackOverflowException' was thrown.' was showing when I attempted to use this same tactic of storing the form as a variable in the two forms.
Why is this error occurring? And is there any way I can overcome it?
Finally, during some reading to counter this issue I discovered the use of controls and panels, and in this way, I could create an interface that opens different the different forms in a panel
However, my attempt of this required the use of anchors to get the form to display remotely true to the Designer appearance
If I do not require the form to be resizable, how can use panels to display a different form and at that in a way that displays the design elements how I have them positioned
Apologies again for my beginner understanding and use of terminology, feel free to seek clarification for crucial details I probably haven't included haha,
Thank you!
I used the following, not sure it's best practice. I used a button ShowFrmHubButton and disabled it when the window is already shown.
In my example the second form is modal, and you can't use the first window as long as the second is displayed.
ShowFrmHubButton.IsEnabled = false;
var frmHubWindow = new frm_hub ()
{
Owner = this
};
frmHubWindow.ShowDialog();
ShowFrmHubButton.IsEnabled = true;
Then, when you close\cancel the second form use this.Close();
Related
I have been looking for some time on ways to open a second form from another already shown form.
This is some piece of code that works:
frmSecond second = new frmSecond();
this.Hide();
second.ShowDialog();
this.Close();
What it does basically is to Hide() the currently opened form, then it opens another form (the ShowDialog() method). It will only Close() the currently hidden form when the form you have just created is closed.
The problem here is: this way of doing it creates an immense thread of forms. If I need to go from frmSecond to frmThird, it will maintain the first form and the frmSecond being executed in the background, while only showing the frmThird.
Then, as the frmThird is open, if I need to get back to the first form, I would use some code like:
frmFirst first = new frmFirst();
this.Hide();
first.ShowDialog();
this.Close();
And it would create another frmFirst! Then we would have three forms being executed in the background (the first frmFirst, frmSecond, and frmThird).
This method works, but uses an increasingly amount of processing memory, which may be prejudicial for any kind of project.
Is there any alternative or add up to correct this problem?
If anything is unclear, please don't bother in letting me know.
Thank you.
If you want to get access to already created forms try using the static Application.OpenForms property. It contains a list of all of the forms currently open in your application. Documentation is here.
As an example, if you always want to keep frmFirst open and then navigate back to it when you close one of your other forms you can do this:
frmFirst existing = Application.OpenForms.OfType<frmFirst>().FirstOrDefault();
if (existing != null)
existing.Show();
You would need to remove your this.Close() calls for this to work.
To free the memory you need to dispose the form using the Dispose method when it is no longer needed.
Seems like you have a desing error here
Then, as the frmThird is open, if I need to get back to the first
form, I would use some code like:
frmFirst first = new frmFirst();
this.Hide();
first.ShowDialog();
this.Close();
This will leave the original created frmFirst in memory, not visible, doing nothing but eating memory.
If you know you want to get back to frmFirst that was created before, why not just do this :
frmFirst.Show();
and save you lots of memory.
You have 2 choices actually
Hide forms and reactivate them when needed
Close and dispose forms, and recreate them when needed
What you are doing is creating each form over and over again, without getting rid of the prior created forms. Hence you need lots of memory for hidden forms...
I'm almost done doing a Connect4 game with VS2012 using WinForms. Everything is working well but I wanted to bring the options for the user on a dedicated Start Menu window. On that menu I have two comboBoxes I need to take the text from to use them as a value for two variables in my other form (the game window). I also have one New Game button that should call a method from my other form if that's possible (basically, I made an "Initialization()" method in my game form and I'd like it to be launched when I click the "New Game" button on the other form).
I only found tutorials that show how to do very basic things from one form to an other (such as labeling texts) but I I didn't find an answer to my specific problem.
I used this in my main form to instantiate the menu form
public FormMenu myMenu;
myMenu = new FormMenu();
What I want to do is that I could do something like this in the other form :
amountOfRows = Int32.Parse(myMenu.comboBoxRows.Text);
amountOfColumns = Int32.Parse(myMenu.comboBoxColumns.Text);
Any idea how I could do that?
I would love to see some example code so I can help see where your confusion lies. WinForms requires the other form to be instantiated.
OtherForm form = new OtherForm();
Once the form is instantiated you should be able to run code from it.
EDIT:
Based on your implementation I would suggest making public methods within FormMenu that return these int values.
public int ReturnRows()
{
return Int32.Parse(myMenu.comboBoxRows.Text);
}
public int ReturnColumns()
{
return Int32.Parse(myMenu.comboBoxColumns.Text);
}
Then from the other form in which myMenu is instantiated you can call myMenu.ReturnRows() and myMenu.ReturnColumns()
The easiest way would be to store a reference to your form in the menue as a variable. (you already named it myMenu)
Then you should create the property/properties you need in the form an add a setter for the values. (see example here)
Last you update the form fields with
myMenu.property = newvalue;
That`s all about it
I'm new in C#, and I wanted to know if there was any way to show a screen with certain elements, and then with the click of a button, switch to another screen, similar to an installer.
From my experience in Java, I would just use a few JPanels and then hide only the one i want visible.
However, I'm new to C# forms and it's very different from Java swing. Anyone understand my problem and can tell me pretty much how this works? Thanks.
Simple approach
Just use a Grid with multiple Grids inside of it. Set the Visibility property of each internal Grid (except the first one you want to show) to Hidden or Collapsed, and then set them to Visible when you want to display them.
Better approach
Create a class for each section, each of which derives from the same parent class. Create a DataTemplate for the parent class, then just have instances of the template load into the original Grid through a ContentPresenter.
You can try this creating new forms. From my experience I've tried this:
Form2 formTwo = new Form2(); // creates instance
formTwo.Show(); // displays the new form
this.WindowState = FormWindowState.Minimized; // minimizes previous form
this.ShowInTaskbar = false; // hides it from taskbar
Keep in mind that this does not close the previous form. I would recommend setting ShowIntaskbar as True if you don't mind the user seeing the form minimized.
EDIT: If you want to show new elements I suggest you can try adding a new Form class to the project then using the designer.
I have a tricky problem here that I have not been able to solve and neither have the people I asked on msdn forums.
I am using a third part product (signal lab from mitov.com) which is a set of .net components.
I have created a windows form app that works fine if it is run.
I now want to show this form from another form when this other form loads (or shows, or activates...).
I already have examples of this working with another form: Here is the typical code:
I am loading a form (SecondForm) from the main program...
private void SecondForm_Load(object sender, EventArgs e)
{
Form _macros = new Macros(this); //this works perfectly fine
_macros.show(this);
//this is where I have no success
Form _spectrum = new SpectrumScope;
_spectrum.Show();
}
I get various errors from no form displayed and then an exception about not instantiating the _spectrum, to an error about cross threaded operation not being allowed, to a blue screen with a message about clocks not being synchronized between processors.
If I place a button on "Second Form" and add the show form code to the click event, it works fine.
If I try to use form.activated, or form shown instead of form.load there is not difference.
If I add a time to form Shown, which then does a button.performClick, there is no difference.
Obviously the form which contains many components (and many threads behind the scene) does not like the fact that it is not being opened by the user.
I'm fairly new to C# and I'm pretty sure this is threading related.
Thank you for any help.
Try the blow code in your form load method, that should let .Net manage the threading for you.
this.Invoke(new MethodInvoker(() => (new SpectrumScope).Show()));
Well, the problem is fixed. However, I don't really know why the issue exists.
In the spectrum form I reference static variables in the secondform. Now, I use them as follows:
string newFrequency = secondForm.frequency;
This works. However, some of these variables need to have this done:
string newBandWidth = secondForm.bandwidth.substring(2,4);
This is the command that fails. I am told I need the "new" keywork.
I changed my code provide the the string without the need to get the substring and now it all works ok.
Anybody have any ideas?
Working with DevExpress 2012 vol 2.10
C# on top of VS 2010
First question seems to have been unclear...
So lets clear it a bit (or try to at least)!
We are building a MainForm with a Ribbon containing many buttons. Every button in the Ribbon is disabled until their respective state is "ready to enable".
"ready to enable" depends on one thing : The WinForm_Popup associated with the button has been completely built, including data retrieval and DevExpress.ExpressApp.ListView construction.
Retrieving data from database takes less than 0.1 second
Calling the WinForm_Popup.Show() takles over 15 seconds
We tried to put this in a Thread or a Task, with no success: It crashes on WinForm_Popup.Show() with an exception related to the DragDrop Event.
What I know by now, is Show() method takes long, but I don't have a clue what happens in this method, but constructing the DevExpress.ExpressApp.ListView, which should be taken away from Show (or do it in a Task or Thred maybe).
Or, in other words, having the WinForm_Popup UI completely built as when it's shown but doing this asynchronously (like in a separate Task, for example).
Any idea, advice, help, link, suggestion, tip... Any "thing" ?
Make a new form and make it empty. In the program.cs file change your main form to the new form. Then make the new form constructor be like this:
public newForm()
{
this.Hide();
Thread backTh = new Thread(() =>
{
MainForm mf = new MainForm();
mf.Show();
});
backTh.Start();
}
I would go for the opposite approach, one that is usually used in slow loading systems like a web browser. Why don't you load the form fast, then use a thread to populate your slow loading grid view?
That way, you can have like a spinning hourglass (or something less 1995) that will tell your users that the data is loading.