I'm writing a simple WinForms app that parses a text file for correct values, and as it finds an incorrect value, opens up a new form, which displays the incorrect or missing value, with the user being able to input the correct value. I have the problem where, for example, I'll deliberately put two incorrect values in my text file to check, and the form window closes immediately after its opened for the first error,and only stays open for the second error to be fixed.
foreach (string line in lines)
{
string[] items = line.Split('\t').ToArray();
for (int i = 0; i <custIndex.Count; i++)
{
int index = custIndex[i];
Globals.Code = items[index - 1].ToUpper();
if (!CountryList.ContainsKey(Globals.Code) && !StateList.ContainsKey(Globals.Code))
{
form2.textBox1.Text = Globals.Code;
form2.Show();//Shows form2 for user to enter correct input
}
}//inner for
}//inner for each
Here's the form 2 code (form 2 being instantiated at the beginning of the method before the looping):
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
//
private void button1_Click(object sender, EventArgs e)
{
Globals.Code = textBox2.Text;
this.Close();
}
private void Form2_Load(object sender, EventArgs e)
{
}
}
The user is supposed to press the button after entering a new value for Globals.Code (I used a global variable, not sure if that was the most kosher way of doing things).After which the form closes and goes back to Form 1. I think form 2 is being displayed properly with the first error value from the text file, but it immediately opens and closes. Is there a way to keep the window open? I'm sorry if this is convoluted, I'm doing a lot of Winforms and I'm not really an expert on this stuff.
Thanks,
Amanda
Your best bet may be to use a modal dialog, so change form2.Show to form2.ShowDialog.
However, when using a global variable with a loop like that, the global variable will only have the last value put into the form after the loop is complete. If you use the ShowDialog approach, the call will block at that line until the user closes the dialog. After that point you can read the value from the textbox and do something with it.
Related
In a c# I have two forms: Windows Form1 & Windows Form2.
When I click on a link label in Form1, the second form is shown. But when I close the second form, my first Windows form closes too.
my main form is:
namespace Windows_Forms_Basics
{
public partial class ShowLocationOnMapForm : Form
{
private string latitude;
private string longitute;
private GeoCoordinateWatcher watcher = new GeoCoordinateWatcher();
public ShowLocationOnMapForm()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
watcher = new GeoCoordinateWatcher();
// Catch the StatusChanged event.
watcher.StatusChanged += Watcher_StatusChanged;
// Start the watcher.
watcher.Start();
}
private void button_ShowOnMap_Click(object sender, EventArgs e)
{
textBox_Latitude.Text = latitude;
textBox_Longtitude.Text = longitute;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "<Pending>")]
private void Watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e) // Find GeoLocation of Device
{
try
{
if (e.Status == GeoPositionStatus.Ready)
{
// Display the latitude and longitude.
if (watcher.Position.Location.IsUnknown)
{
latitude = "0";
longitute = "0";
}
else
{
latitude = watcher.Position.Location.Latitude.ToString();
longitute = watcher.Position.Location.Longitude.ToString();
}
}
else
{
latitude = "0";
longitute = "0";
}
}
catch (Exception)
{
latitude = "0";
longitute = "0";
}
}
private void label1_Click(object sender, EventArgs e)
{
}
private HelpForm form2 = new HelpForm();
private void linkLabel_help_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
this.Hide();
form2.Show();
}
}
}
and my second form is:
namespace Windows_Forms_Basics
{
public partial class HelpForm : Form
{
public HelpForm()
{
InitializeComponent();
}
private void HelpForm_Load(object sender, EventArgs e)
{
}
private void button_BackToForm1_Click(object sender, EventArgs e)
{
ShowLocationOnMapForm form1 = new ShowLocationOnMapForm();
this.Hide();
form1.Show();
}
}
}
Do you have any idea how to tackle this problem?
I am guessing you may be “confusing” forms and one forms “ability” to access another form. Let’s start by taking a look at the bit of code in your initial question…
private HelpForm form2 = new HelpForm();
private void linkLabel_help_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
this.Hide();
form2.Show();
}
This code is called from (what appears to be) a Form named ShowLocationOnMapForm.
On this form is a LinkLabel named linkLabel_help and its LinkClicked event is wired up and is shown above.
In addition, there appears to be a “global” variable form2 that is a HelpForm object (first line in the code above), which is another form. It is unnecessary to create this “global” form variable in the ShowLocationOnMapForm. …. However, we will continue as it is not pertinent at this point.
When the user “clicks” the `LinkLabel’ the above method will fire.
On the first Line in the method…
this.Hide();
Is going to “hide” the current form ShowLocationOnMapForm … and “show” the second form (HelpForm) with the line…
form2.Show();
On the surface, this may appear correct, however, there is one problem that I am guessing you are missing. The problem is…
How are you going to “unhide” the first form ShowLocationOnMapForm?
The second form (HelpForm) is “shown”, however, it isn’t going to KNOW anything about the first form. In this situation the first form is basically LOST and you have no way of accessing it. Therefore when you attempt the line… form1.Show(); in the second form, the compiler is going to complain because its not going to know what form1 is. In this code, there is NO way to get back to the first form. It is not only hidden from the user, but from the second form’s perspective the “CODE” can’t see it either!
Your faulty solution is not only “creating” another form1 but it is also doing the same with the second form.
Given this, it appears clear, that if you want to keep access to the first form… then you are going to have to use a ShowDialog instead of Show OR pass the first form to the second form.
Since it is unclear “how” you want these forms to interact, I can only proffer two (2) ways that you can use to at least keep access to the first form.
1) Use ShowDialog instead of Show when displaying the second form. It may look like …
private void linkLabel_help_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
HelpForm form2 = new HelpForm();
this.Hide();
form2.ShowDialog();
this.Show();
}
In the code above, the ShowDialog is going to “STOP” code execution in the first form and will wait for the second form (form2) to close. When executed, the first form is hidden, then the second form is shown, however, unlike the Show command, the line this.Show(); will not be executed until the second form closes. I am guessing this may be what you are looking for.
2) Pass the first form to the second form giving the second form “access” to the first form.
This will require that the second form has a “constructor” that takes a ShowLocationOnMapForm object as a parameter. With this, the second form can create a “global” variable of type ShowLocationOnMapForm that “points” to the first form. The constructor may look like…
private ShowLocationOnMapForm parentForm;
public HelpForm(ShowLocationOnMapForm parent) {
InitializeComponent();
parentForm = parent;
}
In the first form, you would instantiate the second form with...
HelpForm form2 = new HelpForm(this);
With this approach, the second form will have total access to the first form. You could add the “back” button as you describe and simply execute the line…ParentForm.Show(); However, I recommend you also wire up the second forms FormClose event and show the first form, otherwise, if the user clicks the close button (top right) and doesn’t click the “back” button, then you will have LOST the first form again.
Without knowing “exactly” how you want these forms to interact it is difficult to proffer a complete solution.
There are also other ways to accomplish this, however these should work for most cases.
I hope this makes sense and helps.
I tried to solve this problem by placing a 'Back to Form1' button in Form2. Which works, and the solution is as follows:
on my Form1 I have:
private Form2 form2 = new HelpForm();
private void linkLabel_help_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
this.Hide();
form2.Show();
}
and on my second form I have:
private void button_BackToForm1_Click(object sender, EventArgs e)
{
HelpForm form1 = new HelpForm();
this.Hide();
form1.Show();
}
But the problem is if I click the close button (on top right of the window) instead of the GoBack button on the second form, Form1 & Form2 both close in the same time.
I'm making like a add contact form with two buttons, ADD CONTACT and EDIT CONTACT. When a user clicks add contact, it pops up another form where the user can add contact information.
I want to give them the option to edit that info by clicking the EDIT CONTACT button which should pop up the SAME form.
However its not letting me call the object of the form twice, saying that I cannot press the edit button after the add button.
How do I call a form object twice?
//instatiating an object of the form
FormContact contactForm = new FormContact();
public FormManager()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
//displaying it when the user clicks add button
contactForm.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
//trying to display it again but gives this exception
///System.ObjectDisposedException: 'Cannot access a disposed
///object.
///Object name: 'FormContact'.'
contactForm.Show();
}
Error:
///System.ObjectDisposedException: 'Cannot access a disposed
///object.
///Object name: 'FormContact'.'
The problem is you're closing the form after you've shown it.
You click the Show button
Your only instance of the form is shown
You close it with the X in the top corner
The runtime destroys the form (disposes it) after it is closed
You try to show it again but this this it's gone, trashed, doesn't exist any more, waiting to be garbage collected
Either make a new form each time you open it (to reduce code clutter, assign this same event handler to both button clicks, or copy paste it out twice if you want them to be coded differently eventually):
private void btnAddOrEdit_Click(object sender, EventArgs e)
{
new FormContact().Show();
}
Or intercept the FormClosing event of the FormContact form and cancel the closing, and perform a Hide() instead so that instead of being destroyed your form is made invisible. It will then still exist and can be Show()n the next time. To handle the event, open the FormContact designer, click anywhere in the form background, click lightning bolt in properties grid, double click the FormClosing entry:
private void FormClosing(object sender, FormClosingEventArgs e){
e.Cancel = true;
this.Hide();
}
Which method you choose depends how you want your program to behave:
If you make a new form each time, and you Show instead of ShowDialog your user could click Add twice and see two forms. Then could click Add 10 times and see 10 forms. Using ShowDialog means that the main window won't accept any more clicks until the FormContact is closed. You might or might not want this either
If you Hide (not close; hiding is different from closing) and Show the same form rather than making a new one then the user can click Add 10 times but they still only see one form
FormContact contactForm = new FormContact(); is a Member variable, it's scope is Private and is visible to the entire class.
After you first Show the form:
contactForm.Show();
The form is already showing. Therefore if you call Show again, it won't do anything as the instance of the form/class is already showing.
If you want to show two instances of the form, you will need to instantiate two instances eg:
private void btnAdd_Click(object sender, EventArgs e)
{
FormContact contactForm = new FormContact();
contactForm.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
FormContact contactForm = new FormContact();
contactForm.Show();
}
Or make two instances of it:
FormContact contactForm1 = new FormContact();
FormContact contactForm2 = new FormContact();
private void btnAdd_Click(object sender, EventArgs e)
{
contactForm1.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
contactForm2.Show();
}
Or add a argument in the parameter of the Constructor to indicate Add or Edit, eg:
public class FormContact
{
public FormContact(int id)
{
if (id > 0)
{
//Load contact for Editing
}
else
{
//Clear all fields for Adding
foreach(var ctrl in this.Controls)
{
if (ctrl Is TextBoxBase) ctrl.Text = string.Empty
//TODO other controls types... if (ctrl Is ....
}
}
}
}
Then you can call it passing a contactID to edit or 0 to add:
FormContact contactForm = new FormContact(contactID);
contactForm.Show();
I've got another answer, in both methods simply show your form modally:
contactForm.ShowModal();
I am making a program for a friend and I need it to be were when she types in a number corresponding to the form that opens when she hits 'go' that form will open. I have that part done. The issue I have is when the new form opens I have a series of text boxes that she needs to input data into like '1 can of fresh beans' and some other stuff in some other text boxes on that form. Now when she is done typing in all the required things she will hit a submit button that will then format the code accordingly to the way I have it set to like this
richTextBox1.Text += "This is some text that I type before" + AmntItemsTxtBox + " and this is some other stuff";
So that is what I kind of want to happen. Now I know I may have confused some people but what I ran into as an issue is how do I take what she typed in form 2 and send it to the richtextbox in form 1 when she hits the button so she can copy and paste it into something else later on. I know my code seems a bit "new" but I am just starting out with C# and wanting to learn more. Any help is appreciated.
I have done it in my sample project. It may help you.
Form 1:
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.txtmessagechanged += new EventHandler(txt_messagechanged);
frm2.ShowDialog(this);
}
private void txt_messagechanged(object sender, EventArgs e)
{
txtMessage.Text = (string)sender;
}
Form 2 :
public EventHandler txtmessagechanged { get; set; }
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (textBox1.Text != string.Empty)
{
string a = textBox1.Text;
if (txtmessagechanged != null)
txtmessagechanged(a, null);
}
else
{
MessageBox.Show("Fill some data in textbox");
e.Cancel = true;
}
Image of form 1 (on button click event it open form 2):
Input in form 2 (put some value in text box) :
Get text in form 1 on form 2 close event.
You can modify it according to your needs.
Form 1
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2(textBox1.Text);
frm2.Show();
}
From 2
public Form2(string msg)
{
InitializeComponent();
textBox1.Text = msg;
}
That is how you pass data (or at least one way of doing it). Then you can do whatever you want with it and format it however you like.
I want to pass a parameter to the textbox. I have the following code and it is passing the parameter but not the way I want.
My main form in already open and I want to pass the parameter from my search form. when I do with the code below it opens mt 1 more main form and the parameter is shown in there. I want to by able to show in the opened main form.
When I erase frmMain.Show(); nothing happens.
Main frmMain = new Main();
artikal = "TEST TEST";
frmMain.ed_artiakal.Text = artikal;
frmMain.Show();
any suggestions?
You have many variants to solve your problem.
Option 1
Define and use custom event.
Search form code:
public event EventHandler ArtikalTextChanged;
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (ArtikalTextChanged != null)
ArtikalTextChanged(this, EventArgs.Empty);
}
Main form code:
private void button1_Click(object sender, EventArgs e)
{
Search search = new Search();
search.ArtikalTextChanged += OnArtikalTextChanged;
search.Show();
}
private void OnArtikalTextChanged(object sender, EventArgs e)
{
this.ed_artiakal.Text = (sender as Search).textBox1.Text;
}
Don't forget to make textBox1 of Search form public.
Option 2
Get instance of your main form in search form:
Search form code:
private void textBox1_TextChanged(object sender, EventArgs e)
{
var mainForm = Application.OpenForms.OfType<Main>().FirstOrDefault();
mainForm.ed_artiakal.Text = textBox1.Text;
}
Main form code:
private void button1_Click(object sender, EventArgs e)
{
Search search = new Search();
search.Show();
}
Don't forget to make ed_artiakal control public in your Main form.
Option 3
Share data between forms (recommend)
But if you application is large and you want to make it scaleable and flexible I recommend you to use data-binding technique to share data between forms without coupling them. You can read more at articles: http://msdn.microsoft.com/en-us/library/h974h4y2(v=vs.90).aspx
I have solved my problem in the following way.
On my Search Form I created a public string and when I showed the form I referenced to that string in my case GetItemCode.
The key here was to use ShowDialog() and not to use Show().
SEARCH FORM
Search frmSearch = new Search();
frmSearch.ShowDialog();
ed_artiakal.Text = frmSearch.GetItemCode;
MAIN FORM
public string GetItemCode
{
get { return Artikal; }
}
Now when I close the search form the value is shown in the TextBox on my main form.
Thanks for your answers and comments!
What is the best way to close a form and get to another form.
At present I have a Main Form and then two forms:
I want to know how to close one form and open another form efficiently.The two times I did it had a slight different outcome:
The main form in my application is just the introduction which will load some Company Logo and show a progress bar which will then take it to a log-in form, where in I have a log-in button, from where the actual application will open.
I have some questions.In the Main Form I have added this code:
private void Form1_Load(object sender, EventArgs e)
{
int i;
for (i = 0; i <= 100; i++)
{
progressBar.Value = i;
label1.Text = "Please wait while Refresh loads up...";
}
}
private void progressTimer_Tick(object sender, EventArgs e)
{
this.Close();
}
private void MainForm_Deactivate(object sender, EventArgs e)
{
Form form = new FirstForm();
form.ShowDialog(this);
}
1) This works fine, just that the new form that opens up is at the task bar and is not in the center of the screen(as I have set it's property).How do I fix this?
In the First Form I have added this code:
private void loginButton_Click(object sender, EventArgs e)
{
using( ERPQueries eq = new ERPQueries())
{
int? count = eq.CheckEmployee(userTextBox.Text,passwordTextBox.Text);
if (count == 1)
{
//testLabel.Text = "Ok";
this.Close();
Form form = new SecondForm();
form.ShowDialog(this);
}
else
{
testLabel.Text = "Invalid username or password!";
}
}
}
2) Here the next Form pops up in the center of the screen.I want to know how is it different from the first case, as I have used showDialog() in both the cases?
3) Also in the first case my Main Form Disappears, whereas in the second case the First Form is still visible in the background and disappears only after closing the SecondForm.
I'm sure I'm doing a lot of mistakes, my code is flawed.Please help.This is the first time I'm making an application with multiple forms.
Edit:
When I use Show() instead of ShowDialog() I don't see the new form.Am I missing something?
I tried this.Dispose() instead of this.Close().In the first case it works fine.In the second case, it disposes all the forms.
try:
form.Show();
not
form.ShowDialog(this);
which is what makes it modal.
ShowDialog() is blocking call, so if in one Form's deactivate event you call ShowDialog() of another, your parent form will not yet finish it deactivating.
Like a suggesion I can give you create a collection/stack of forms you want to manage and give control over it to a FormManager class, where you implement whatever logic you want and can call either ShowDialog() or Show(). In other words bring out forms Show/Hide management out forms itself.
Regards.