I am trying to create a simple c# application (my first attempt at c# so please be kind). I've created a form with a textbox to capture an "auth code", which is then validated and then a webclient fetches an xml file passing this auth code in to the request. The data sent back is parsed e.c.t.
What i want to do is once the xml comes back and ive done my checks to valid it is all fine. I want to close the first form and load up a second form where i will programmatically add the form components needed to display the xml data in a pretty format.
My problem is that im unable to get the second form to stay open (im no doubt invoking the second form in the wrong manner). Here's what i have:
// close current form
this.Close();
//open new form
xmlViewForm xmlView = new xmlViewForm();
xmlView.Show();
I'm sure you've spotted the mistake im making by now. but just to state the obvious for the sake of completeness, it closes the first form, opens the second, and then immediately the program exits (the second form flashes up for a second obviously).
I've tried a few things but none of them work (including using Application.Run(new xmlViewForm()); instead of instantiating the class and using the show() method. Obviously you know that doesn't work, and now i do too, although i dont understand c# even remotely enough to work out why.
Thanks for any help :)
The first thing that came to mind is that you are closing the form that you opened by calling Application.Run(new MyForm()) or something similar. This form has special significance; it is the "main form" of the application, and when closed, it signals to the application that the user wants to close the entire program, no matter how many other windows are open.
There are two possible fixes. First, and easiest, is simply to Hide() the form you don't want visible instead of calling Close() on it. Though invisible, it's still running, so the application doesn't close.
The second solution is to define a custom "application context" that should be run instead of the "default context" that is created by specifying a main form to watch. You do this by deriving a custom class from System.Windows.Forms.ApplicationContext. With this context specified, you can use it to control termination of the application based on something other than closure of the main form. Example code that launches two "main forms" and keeps track of whether both are still active can be found at the MSDN page for the class. You can do something similar by specifying Load and Close handlers for the main form, then passing them to the child form when the main form instantiates it, thus keeping a count of "open" forms, and closing out the full application when that number is zero. Just make sure the child form loads before closing the main form by calling childForm.Show() before this.Close().
You can not open the second form after closing the main form.
Do this:
//open new form
xmlViewForm xmlView = new xmlViewForm();
xmlView.Show();
// hide current form
this.Hide();
Main form can not be closed because it's the parent form. The child form will never show up if you close the main form.
Or change the xmlViewForm to main form by editing Program.cs file
Application.Run(new XmlViewForm());
Then you can easily call the other form first at the time of loading and close it as you please:
private void XmlViewForm_Load(o, s)
{
// hide current form, and this will remain hidden until the other form is done with it's work
this.Hide();
//open the other form
TheOtherForm _theOtherForm = new TheOtherForm();
_theOtherForm.Show();
}
private void TheOtherForm_Closed(o, s)
{
// show current form
this.Show;
}
Related
I have a selection of TextBoxes that a user fills in when they wish to note that they have had contact with another person. Most of the TextBoxes are imply filled in by typing into them. However, for one of them I would like the user to be able to select from a list of People that appears when they click on a button.
This is where I am having problems. So far I have just made a DataGrid appear and handled it's SelectionChanged method to fill in the TextBoxes text property. This has worked fine, however now there is not enough space on the current page to show an entire DataGrid with all the people they can select from.
I've decided to show the People in a separate, smaller Window that appears when the user clicks a Button. The issue I have is that when the user selects the Person they wish to mark the contact for in the new Window, I have no idea how I can notify the original Window that a Person has been selected, close the new smaller Window and fill in the appropriate TextBox on the original Window.
What would be the most intuitive way to fill in the TextBox on the original Window, based on the selection on the Window that opens?
I would use delegates,which call a function of the original window and parse the changed variable with it. So you know when the user clicked something and you can directly react to this "event".
Link:
https://msdn.microsoft.com/en-us/library/ms173171.aspx
If you use a framework like Galasoft's MVVM Light (http://www.galasoft.ch/), they have a messenger system just for this purpose. It allows you to "broadcast" messages that can be "received" by any other part of the application
This is when considering using Domain, Model, Presentation (Winforms/WPF version of MVC formatting) to do your app.
You can have each form as its own class, well they are their own class. Create each form class but add some public members to it if the controls are private. Have them have "get" properties only and to return the values of whatever controls or variables are in that form. Your main form will be the controlling form. All forms will be handled by the main form so when you open it, it is a class the main form can access.
Now, if I remember (been doing more MVC and not any Winforms lately) I believe if you use the ShowDialog() method it will freeze the main thread so when you close out the main form you can continue and read in public members you have in your forms class you opened. Synchronous I believe it runs as. If you use just Show() the thread will keep on trucking, asynchronous. With asynchronous you may then have to use a main form in your startup code so there is always a window there but subscribe to the close event of your forms and have a method that can grab those public members out. Be sure to instantiate the extra forms at the root of the main class so it doesn't fall out of scope when it exists the method that calls it. You may even be able to make the method that calls is a async call and have an await before the command that runs the Show method on the form.
Summary, treat each form as its own class but add public members that can read the values from the controls and/or variables you want. Read that data from the class when it closes via an event or synchronously when the thread closes out from the form closing. The form closing doesn't discard the object, just the visualization of the form.
Oh, if you are passing info from the main form to a child for you are opening, either add a constructor for that form class that takes your input as a model or values to fill in the appropriate variables or forms before showing it or create a public property you can put your values you want to send in before showing the class.
Remember, everything is a class, once you look at it as such and treat it as such, the answer will come. :-)
I should warn, I am a long winded explainer.
At work putting all this down from memory so some errors may exist. Let me know if there are.
I think the problem is to access the controls of the main window, isn`t it?
You can define an event of changing user`s choise and access MainWindow control by using the following construction:
((MainWindow)Application.Current.MainWindow).MyTextBox
I have a very simple GUI application in C# and there is some codes in Form Load function. I just want to start and close the application without showing Form for running those codes in form load function.
How to do it?
If you don't want to show a form, you should move your code to the Main() method and get rid of the form.
Or you could try to create a service which contains no GUIs
http://msdn.microsoft.com/en-us/library/zt39148a%28v=vs.110%29.aspx
form.Opacity = 0;
I am not sure if this is what you want.
EDIT: - This will keep form opaque and you can run and close it when an event occur.
I have 3 forms. How can I make it so that one form is shown with .Show() and the other is hidden with .Hide() from a separate form?
This is part of my code
private void buttonYes_Click(object sender, EventArgs e)
{
LoggedIn loggedinform = new LoggedIn();
loggedinform.Hide(); // Hides another form that is in the background
MainForm mainform = new MainForm();
mainform.Show(); // Show first form
this.Hide(); // Hides current form
}
One problem, the LoggedIn form does not hide itself. From the looks of it it skips it and just goes for the mainform.Show();
Is this a bug or do I need to do something else?
The line LoggedIn loggedinform = new LoggedIn() is going to create a new instance of that login window. That might be useful if, say, you intended to show 5 "Login" windows onscreen all at once. I think what you want to do is retrieve a reference to the login window that is already showing, and hide that; so, avoid creating a new one.
Properly passing references to existing objects around the program is kind of a structural problem, and one that I ran into quite a bit in my early programming days. The quick, unclean, and generally not-recommended way is to declare instances of those singular objects (like, maybe, your login window) as static, so they can be retrieved anywhere. However, to fully answer your question in the best way, maybe you could describe the structure of your program a bit more (full code isn't necessary, just generally-speaking, what the flow is between classes)
Ok I figured it out. I can use
Application.OpenForms[1].Hide();
[1] is the form I'm trying to hide. And it worked.
I also realized thanks to Katana that it makes sense why it wasn't working because it was basically making a new instance of the form instead of finding the current one. Sorry that my code is a mess.
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.
I'm having some serious issues with a WinForm application that I'm working on.
Currently, I'm using Form1.ShowDialog(); to display a form. This code is contained in a background worker that looks for changes in a database. Using Form1.ShowDialog(); only allows 1 form to open at a time, even if there are multiple changes to the database. What I want to have happen is for multiple forms to open at once if there is more than one change in my database.
When I use Form1.Show();, the application blows up. For some reason, the Show() method makes the forms not display properly (all the elements in the form are missing).
Is there anything I can do to make my code work the way I want it to?
Edit: here's a code snippet
//result is a linq result
foreach (var row in result)
{
Form1 Form = new Form1();
Form.ShowDialog();
}
After a first look, I can tell you this:
Showdialog can't work the way you intend: this very method makes the owner inactive until the dialog is closed. In your case, the loop will pause at the first showdialog, then resume when you close the form, opening a new one and so on until the loop is finished.
As for the "show" problem, creating empty forms, I need more information. The rest of the code and the exception(s) you're getting.
Two points from the top of my head:
1) To open more then one form , use non modal (modeless) method (i think
the show() method). see for example http://msdn.microsoft.com/en-us/library/39wcs2dh.aspx
2) I am not sure you can call UI related method from a non UI thread. You might want to send an event to your UI thread from the worker thread and the UI thread will call the show method