I have mainVariable.cs that contains delegates for events. Also I have several forms and a worker.cs. My problem is that Login form is starting form and handles some event. After that it hides itself and shows another form. Now the problem starts here, because second form which started after login, cant handle any events. I mean when I raise an event from worker.cs and login form handles the event not the second from even if I dispose the login form. How can I solve this puzzle ?
Apply this to your Programm.cs
Application.Run(loginForm);
if (loginForm.IsLoggedIn == true)
{
ERS_FDData.ERSUser user = loginForm.user;
loginForm.Close();
Application.Run(new frmMain(loginForm.user));
}
else
Application.Exit();
After the login is done, you need to set the Mainf Frame to be the application default window
For any event to be handled you need to assign it a subroutine.
You can do this from any form, given you initialize and show it first.
For example.
Form1
{
FormLoad()
{
mybutton.click += new EventHandler(myfunction);
}
myfunction(object o, EventArgs e) { // Dostuff }
}
So you'd initialize Form1 something like this
Form1 myform = new Form1();
And the event will work as the form expects.
Related
I am having a problem controlling a textbox. I need to change a value from outside of Form1.cs where the textbox is located for this I have found this snippet.
public void UpdateText(string newValue)
{
torrent_name0.Text = newValue;
}
this allows me in theory to control the textbox outside of Form1.cs, but here comes the problem, every time I want to access it I create a new instance of Form1 instead of using the old one and refreshing it.
Form1 frm = new Form1();
frm.UpdateText("aaaaaaaaaaaa");
frm.Show();
am I missing something? is there a better way to do this? I have tried multiple ways to update the new form but got nowhere.
Bokker,
You will have to have a reference to the singular form1 to which all things refer.
If this is a child form, then as Aybe commented, create a public member of your mainform and name it something.
Public Form myForm1;
You probably have some Event by which you would like Form1 be launched...
A Button click, menu item, toolbar item, etc. In that event you will have to check if the form exists and create if required.
private SomeEvent() {
if (myForm1 == null)
{
myForm1 = new Form1();
myForm1.Show(this);
}
myForm1.UpdateText("some text");
}
Alternatively, you could create the form in the Form Load event, just so long as you create the form prior to attempting the myForm1.UpdateText()
If you follow this paradigm, you are creating myForm1 as part of the main form, best practice says you should also dispose of the form in your main form Closing Event.
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (myForm1 != null)
{
myForm1.Close();
myForm1.Dispose();
}
}
This is all off the top of my head, so it might not be perfect.
In that case you can pass the instance of form in the method as argument and make the changes like
public void UpdateText(string newValue, Form1 frm)
{
frm.torrent_name0.Text = newValue;
}
I have a button and hidden textbox on my main form. When I press the button it will hide the main form and show the second form. When I press the button on the second form I want to show the main form again but this time I need to show the hidden textbox. I know how to pass the text from a textbox to another form but not just the reference of the textbox.
You better pass the complete main form instance for the second form, and create a public function to set the textbox to visible, or create a property around it.
Something like:
//form1
Form2 second = new Form2(this);
}....
public void ShowTextBox()
{
textbox1.Visible=true;
}
//form2
Form parent;
public Form2(Form _parent)
{
parent=_parent;
}
///later
parent.Show();
parent.ShowTextBox();
Sounds to me like a custom event would be a better approach. Have the secondary form expose an event, which is raised at whatever appropriate time (your button press). In your main form, when you create your instance of your second form, subscribe to that event. Then run your "unhide" code from within the mainform's event subscription.
This keeps the coupling down on the two forms and results in much more easily maintainable and extensible code (for best effect, use interfaces, but events are a good middle ground for learning).
Something like this:
(it's been a long time since I worked with winforms, or events even, so if this needs refining let me know)
// your secondary/popup form's class
public partial class Form2 : Form
{
// add a custom event
public EventHandler<EventArgs> MyCustomEvent;
// link up your button click event
void InitializeComponent() {
myButton.Click += myButtonClick;
}
// when your button is clicked, raise your custom event
void myButtonClick(object sender, EventArgs, e) {
onMyCustomEvent();
}
// this "broadcasts" the event
void onMyCustomEvent() {
EventHandler<EventArgs> h = MyCustomEvent;
if (h != null) {
h(this, new EventArgs());
}
}
}
// your main form's class
public partial class MainForm
{
void InitializeComponent() {
// ...
}
void showForm2() {
var form2 = new Form2();
form2.MyCustomEvent += form2CustomEvent;
form2.Show();
}
void form2CustomEvent(object sender, EventArgs e) {
myHiddenTextBox.Visible = true;
}
}
All in all this is a much better approach in terms of code architecture. Now the popup doesn't care who opens it (it has no reference to the main form), and the custom event (which is really what you're after) can be managed to any level of control you need, without interfering how other thing work (for example, perhaps later you may want to have a different action that fires this same custom event...)
Food for thought.
When I show a MessageBox with helpFilePath set to some url, the url loads multiple times. It seems to me that the url loads a number of times equal to the number of my forms parents plus one.
Can anyone explain why this is happening?
According to MSDN the HelpRequested event will fire on the active form:
When the user clicks Help button, the Help file specified in the
helpFilePath parameter is opened. The form that owns the message box
(or the active form) also receives the HelpRequested event.
The helpFilePath parameter can be of the form C:\path\sample.chm
or /folder/file.htm.
But I don't understand why raising the HelpRequested event on the parent forms should load the link from the child forms MessageBox.
Am I doing something I'm not supposed to?
This code will reproduce the behaviour:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// First button spawns new instances of the form
var button1 = new Button { Text = "New Form" };
Controls.Add(button1);
button1.Click += delegate
{
using (var form = new Form1())
form.ShowDialog();
};
// Second button shows the MessageBox with the help-button
var button2 = new Button { Text = "Dialog", Left = button1.Right };
Controls.Add(button2);
button2.Click += delegate
{
MessageBox.Show(
"Press Help",
"Caption",
MessageBoxButtons.OK,
MessageBoxIcon.None,
MessageBoxDefaultButton.Button1,
0, // Default MessageBoxOption (probably not related to the behaviour)
"http://SomeHelpSite.com/MyOnlineHelp.htm");
};
}
}
Click "New Form" a couple of times:
Then click "Dialog":
Now, click the help-button:
On my computer this opens SomeHelpSite.com tree times:
I have found a way to block the undesidered behavior and, probably, an explanation why this happens.
To block the opening of undesidered url after the first one you need to simply add an handler for the HelpRequested event. In this event you should inform the WinForms engine that you have handled the help request and no further action is required
public Form1()
{
InitializeComponent();
this.HelpRequested += onHelpRequested;
.....
}
protected void onHelpRequested(object sender, HelpEventArgs e)
{
e.Handled = true;
}
In this way, only one page is opened.
Now the explanation why this happens is, probably, reported at the MSDN page for the Handled property of the HelpEventArgs where you could find this statement:
If you do not set this property to true the event will be passed to
Windows for additional processing.
EDIT Further tests shows that also without setting the Handled property to true, the simple fact that an event handler for the HelpRequested event exists stops the undesidered behavior
I have got the new problem with opening and closing form in C#.
My problem is how to dispose the form after closing .
here is my code :
Program.cs:
static class Program
{
public static Timer timer;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
timer = new Timer { Interval = 1000};
timer.Start();
Application.Run(new Form1());
}
}
Form1.cs:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 form = new Form2();
form.ShowDialog();
/// I've tried Dispose() method . but didn't work
}
}
Form2.cs:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
Program.timer.Tick += timer_Tick;
Close();
// I've tried Dispose() method instead of Close() but didn't work
}
private int count = 0;
void timer_Tick(object sender, EventArgs e)
{
count++;
if (count == 5) MessageBox.Show("");
}
}
Edited :
My question is : why the message box shows after 5 seconds when the form2 has closed!
This question turns out to be about Dispose.
Firstly, Dispose has nothing to do with garbage collection. The following happens:
You have a global Timer instance
You create form2
Form2 subscribes to the timer
Form2 is Closed and/or Disposed
The Timer event fires, increments the counter and shows a MessageBox
The Timer event keeps firing until the App closes.
The main point to understand is that Close/Dispose only change the status of the Form, they don't (can't) 'delete' the instance. So the (closed) form is there, the counter field is still there and the Event fires.
OK, part 1:
A using () {} block would be better but this should work:
private void button1_Click(object sender, EventArgs e)
{
Form2 form = new Form2();
form.ShowDialog();
/// I've tried Dispose() method . but didn't work
form.Dispose(); // should work
}
If not, please describe "doesn't work".
private void Form2_Load(object sender, EventArgs e)
{
Program.timer.Tick += timer_Tick;
Close();
/// I've tried Dispose() method instead of Close() . but didn't work
}
This is strange, but I'll assume that it is artifical code for the question.
Your global Program.Timer now stores a reference to your Form2 instance and will keep it from being collected. It does not prevent it from being Disposed/Close so your timer will keep firing for a Closed Form, and that will usually fail and cause other problems.
Don't do this (give Form2 it's own timer)
Use a FormClosed event to unsubscribe: Program.timer.Tick -= timer_Tick;
The simplest and most reliable way to dispose a Form after using is to put the usage inside of a using block
using (Form2 form = new Form2()) {
form.ShowDialog();
}
The using block in C# is a construct that essentially expands the above into the following code.
Form2 form;
try {
form = new Form2();
...
} finally {
if ( form != null ) {
form.Dispose();
}
}
This is an old question but it touches some interesting points about how objects work. A form is, essentially, an object. All objects of the same class share the same methods but each one has their own data. What does this mean? This means that, closing or disposing an object does not free/delete/remove any code from the memory. Only data. All that was about objects in general, no matter the language.
Now, specifically about your code. Let us examine what the line Program.timer.Tick += timer_Tick; does. This gives a pointer to your function in the Form object to the timer object. So, now, no matter what you do to the Form object, the timer object will keep calling that function. The timer object does not care about your Form and is not even aware of the existence of the Form object. It only cares about the function you passed the pointer to. As far as the timer object is concerned, this function is a standalone function.
What does Form.Close() do? Form.Close() disposes the resources used by the form, aka, marks the form's controls for garbage collection unless the form is displayed using ShowDialog. In that case, Dispose() must be called manually. MSDN
Needless to say(or maybe not so needless) that if closing/disposing the form cleared the function from the memory, the timer object would have an invalid pointer and your program would crash after 5 seconds.
Perhaps I am reading the question wrong, but I think the gentlemen needs to know that, to close a form (say form2) opened as Form2.ShowDialog(), you need to set Form2.DialogResult within Form2. Just setting that member is all it takes to close the form and return the result.
form.ShowDialog() shows the form as a modal dialog. This means that the call doesn't return until the Form is closed.
Note that clicking the close X on a modal dialog doesn't close the form, it just hides it. I am guessing that this is what confuses you.
If you want the code in form1 to continue executing rather than blocking, you should call Show() instead of ShowDialog(). Non-modal will close when the X is clicked.
If you do want a blocking modal dialog, you should surround the form with a using block as described in the other answers.
When building a modal dialog you would typically add an "OK" button or similar and set the AcceptButton property of the form to that button to allow the user to close the form by pressing enter. Similarly you can add a "Cancel" button and set the CancelButton property to capture the Esc key.
Add a click handler to the two buttons, set the DialogResult property of the form accordingly and call Close().
I am working on a DirectX based simulator.
On which I have to check for a device whether device has been plugged-in or removed from the PC.
I've managed to make classes for device arrival and removal on another thread, which raises an event from the thread itself on device arrival or removal.
The corresponding event method is being called in the main form and there:
Assume Form1 is main window and Form2 is the secondary.
Form2 form2Instance = new Form2();
I want to show another Form (Form2) keeping main Window (Form1) in behind (same as it behaves as form2Instance.ShowDialog(); in general cases.)
After a few tries I have done it by
Applicatin.Run(new Form2());, but the Form2 doesn't behave as'form2Instance.ShowDialog(); in any way.
Just giving the code if it can help in answering:
iARMdetectionThreadClass detection;
InProgram_iARMdetection iARMStatusGUI;
private void Form2_Load(object sender, EventArgs e)
{
iARMStatusGUI = new InProgram_iARMdetection();
detection = new iARMdetectionThreadClass();
detection.IniARM_device_Arrive += new iARMdetectionThreadClass.iARM_device_ArrivedEventHandler(detection_IniARM_device_Arrive);
detection.IniARM_device_Remove += new iARMdetectionThreadClass.iARM_device_RemovedEventHandler(detection_IniARM_device_Remove);
detection.startThread();
}
void detection_IniARM_device_Remove(iARM_deviceInfo senderInfo)
{
detection.StopCheckBeingRemoved();
MethodInvoker act = delegate
{
this.label_iARMStatus.Text = detection.iARM_deviceInf.iARMStatus;
};
this.label_iARMStatus.BeginInvoke(act);
Application.Run(new InProgram_iARMdetection()); //Blocking code
detection.StartCheckBeingRemoved();
}
void detection_IniARM_device_Arrive(iARM_deviceInfo senderInfo)
{
MethodInvoker act = delegate
{
this.label_iARMStatus.Text = detection.iARM_deviceInf.iARMStatus;
};
this.label_iARMStatus.BeginInvoke(act);
//detection.StopCheckArriving();
//detection.StartCheckArriving();
}
I need the code to be Blocking Code. In here:
Application.Run(new InProgram_iARMdetection()); //Blocking code
Perhaps mainform.AddOwnedForm(form2) will do what you want. It will make form2 display in front of mainform and when either one is minimized, the other is also.
You should handle the remove event on form2 rather than form1 and use the ShowDialog() method.
So when on form1 the arrival event will fire it will open up form2 like a dialog. Now when the device will be unplugged, on form2 removal event will fire where you can close the form.