I have 2 forms form1&form2. Form1 contains a serial port. This port is opened in form load.
private void Form1_Load(object sender, EventArgs e)
{
serialPort1.Open();
}
I want to write to serial port through form2. For that I created a function in form1 for writing to serial port.
public void SerialPortValueUpdated()
{
byte[] head = new byte[1] { 0xAA };
byte[] trail = new byte[1] { 0x55 };
byte[] llen = new byte[1] { length };
// head = Convert.ToByte(0xAA);
//serialPort1.Open();
serialPort1.Write(head, 0, 1);
serialPort1.Write(llen, 0, 1);
serialPort1.Write(trail, 0, 1);
}
and called this function from form2 like this
private void button1_Click(object sender, EventArgs e)
{
Form1 F = new Form1();
F.SerialPortValueUpdated();
}
But when I calling this function I get an error that 'Port is closed'. How can I solve this.
Please help me.
As was stated in the other answer you are creating a new Form1 in your Buttons click event instead of using the Form that you have already opened the serial port with. In my systems I use a separate class to encapsulate the communication logic as was mentioned in the other answer. But since this seems to be a simple application and your existing Form1 as knowledge of your Form2 since it created it, just pass form1 as the Owner of Form2, that way you can access the function you are wanting.
i.e.
f2 = new Form2();
f2.Show(this); // or f2.ShowDialog(this) if you want f2 to be Modal
You would then access it in your Form2's Button Click something like this.
private void button1_Click(object sender, EventArgs e)
{
((Form1)this.Owner).SerialPortValueUpdated();
}
Form1
public partial class Form1 : Form
{
Form2 f2;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
f2 = new Form2();
f2.ShowDialog(this); // or f2.Show(this) if you want f2 to be non Modal
}
public void SerialPortValueUpdated()
{
MessageBox.Show("Test");
}
}
Form2
public partial class Form2 : Form
{
Form3 f3;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
((Form1)this.Owner).SerialPortValueUpdated();
}
private void button2_Click(object sender, EventArgs e)
{
f3 = new Form3();
f3.ShowDialog(this.Owner);
}
}
Form3
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
((Form1)this.Owner).SerialPortValueUpdated();
}
}
the problem is that creating a new Form1 will never open your port since the Load event will be called when the form get's loaded, and just newing up a form will not load or show it.
The easiest way to change this is to move the opening into the constructor.
So instead of
private void Form1_Load(object sender, EventArgs e)
{
serialPort1.Open();
}
do
public Form1()
{
serialPort1.Open();
}
The better approach
Having said that - using a Form just to do this kind of stuff is really not a solution. Instead use a simple class to do this and make it the responsibility of the caller to manage opening and closing (or if you really just want to write a few bytes then open and close it in your methods).
Related
I can't update the first form of my application. when it opens it loads all the elements, then through a button I open a second form and from that, with a button I should reload all the controls of the first form including form1.text but this does not happen. despite the marker I saw that the text variable is updated correctly, however on a graphic level it does not change.
form1:
public partial class Form1 : Form
{
public string mail { get; private set; }
public Form1()
{
InitializeComponent();
}
public void Form1_Load(object sender, EventArgs e)
{
this.Text = "table - Last Update: " + DateTime.Now.ToString();
...some other code...
}
public void updateform()
{
this.Controls.Clear();
InitializeComponent();
Form1_Load(null, null);
this.Refresh();
}
private void button1_Click(object sender, EventArgs e)
{
mail = lbl1.Text;
Form2 form2 = new Form2(mail);
form2.Show();
}
}
form2:
public partial class Form2 : Form
{
public Form2(String stringa)
{
InitializeComponent();
email = stringa;
}
private void button1_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
f1.updateform();
this.Close();
}
You can pass a reference to Form1, into Form2 using the Show() command. The reference can be accessed using the .Owner property.
In Form1:
private void button1_Click(object sender, EventArgs e)
{
mail = lbl1.Text;
Form2 form2 = new Form2(mail);
form2.Show(this); // <-- pass reference to Form1
}
In Form2:
private void button1_Click(object sender, EventArgs e)
{
Form1 f1 = this.Owner as Form1; // <-- attempt to convert .Owner to Form1
if (f1 != null)
{
f1.updateform();
}
this.Close();
}
I am very new to C# so I am sorry if I use wrong terms. Here is my problem. I have 2 forms. and I want If I click the button in Form1, it shows up the Form2 by overlapping the Form1. And now, if I click the button in form2, I want the form1 overlap the form2. But I always get error "stackOverFlowException". Why did i get the error? How to resolve it? I am sorry if my question is not clear. I hope these picture can explain better about my question.
Here is the code for form1.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Form2 frm2 = new Form2();
private void Form1_Load(object sender, EventArgs e)
{
frm2.Show();
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
frm2.Left += 10;
if (frm2.Left >= 750)
{
timer1.Stop();
this.TopMost = false;
frm2.TopMost = true;
timer2.Start();
}
}
private void timer2_Tick(object sender, EventArgs e)
{
frm2.Left -= 10;
if (frm2.Left <= 535)
{
timer2.Stop();
}
}
}
}
and here is the code for form2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
Form1 frm1 = new Form1();
private void Form2_Load(object sender, EventArgs e)
{
frm1.Show();
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
frm1.Left += 10;
if (frm1.Left >= 750)
{
timer1.Stop();
this.TopMost = false;
frm1.TopMost = true;
timer2.Start();
}
}
private void timer2_Tick(object sender, EventArgs e)
{
frm1.Left -= 10;
if (frm1.Left <= 535)
{
timer2.Stop();
}
You are creating and endless chain of opened forms.
When you first create a Form1 object with new Form1(), the initialization code inside this form
Form2 frm2 = new Form2();
... is called. This in turn triggers the initialization code of Form2, which is
Form1 frm1 = new Form1();
This creates a new instance of this form (now you have two Form1 instances) and calls Form2 frm2 = new Form2(); again in this new instance (now you have two Form2 instances). This goes on until thousands of form objects have been created and the stack overflows.
What can you do about it?
In Form2 add a parameter to the constructor that allows you to pass a reference to the first form
private readonly Form1 _frm1;
public Form2 (Form1 frm1)
{
InitializeComponent();
_frm1 = frm1;
}
In Form1 do this
private Form2 _frm2;
private void Form1_Load(object sender, EventArgs e)
(
_frm2 = new Form2(this);
)
I.e. Form2 never creates a Form1. Instead, it gets a reference to the already opened form.
How do you bring a form to front?
The TopMost property controls the behavior of a form when it is opened. Instead, use
_frm1.BringToFront();
to change the z-order afterwards.
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
it was work before but now not working why i dont know what is the issue?
in example have 2 forms form1 have 1 button form2 have 1 textbox when start the program and click the button form1 should close, form2 open and delegate variable should write in textbox but not work. Error is "System.NullReferenceException occurred"
public partial class Form1 : Form
{
public delegate void kapatici(string al);
public static event kapatici kapat;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
kapat("deneme");
Form2 f = new Form2();
f.ShowDialog();
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
Form1.kapat += Form1_kapat;
}
private void Form1_kapat(string al)
{
textBox1.Text = al;
//throw new NotImplementedException();
}
}
I've tried different types like
private void button1_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.ShowDialog();
kapat("deneme");
}
but still not working.
thank you for your answers.
I'm not sure what you want to achieve with the code - but I think / hope it's just a minimal example. So here is a solution:
Events are null until they are suscribed. You have to check the event before you are going to invoke it:
if (kapat =! null)
{
kapat.Invoke("deneme");
}
A compact way to do this is by using the null-operator:
kapat?.Invoke("deneme");
Second mistake is to show your second form as dialog, because you are blocking your method until the dialog is closed. If your click-method looks like this, it will work:
private void button1_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.Show();
kapat?.Invoke("deneme");
}
If you only want to show a text on your second form, you should not use a event. The simplest way is to pass the string throught the constructor of the second form like:
public Form2(string al)
{
InitializeComponent();
textBox1.Text = al;
}
Now you can open the form with:
private void button1_Click(object sender, EventArgs e)
{
Form2 f = new Form2("deneme");
f.ShowDialog();
}
At first I thought that it won't be a problem for me, but now I can't figure it out. So,
when I click Button1 in main form, form2 opens. Form2 is simple numeric keyboard, that user can enter some data. On form2 is also Save. When user clicks it, entered value should pass to main form and from that moment some event must happen in main form, which contains data from form2. Could you please give me some example or any kind of help? Thanks!
// code from main form to create form2
private void button1_Click(object sender, EventArgs e)
{
// Create a new instance of the Form2 class
Form2 settingsForm = new Form2();
// Show the settings form
settingsForm.Show();
string val = settingsForm.ReturnValue1;
MessageBox.Show(val);
}
//button save on form2
private void button13_Click(object sender, EventArgs e)
{
this.ReturnValue1 = "Something";
this.ReturnValue2 = DateTime.Now.ToString(); //example
this.Close();
//after this, some event should happen in main form !
}
There is a lot of solutions to do what you want; but I think one of these will resolve your problem.
1- Simple and easy: use public properties in Form2, initialize them when buttonSave get clicked, and access them in Form1:
Form2:
public partial class Form2 : Form {
public Form2() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e){
YourDate = "something";
Close();
}
public object YourDate { get; private set; }
}
Form1:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e){
var f2 = new Form2();
f2.ShowDialog();
var data = f2.YourDate;
}
}
2- A better way, is using events which is more flexible and professional programming friendly:
Form2:
public partial class Form2 : Form {
public Form2() {
InitializeComponent();
}
// create an event of Action<T> which T is your data-type. e.g. in this example I use an object.
public event Action<object> SaveClicked;
// create an event invocator, to invoke event whenever you want
protected virtual void OnSaveClicked(object data){
var handler = SaveClicked;
if (handler != null)
handler(data);
}
private void button1_Click(object sender, EventArgs e){
// prepare your data here, -object, or string, or int, or whatever it is
var data = PrepareYourDataHere;
// invoke the event
OnSaveClicked(data);
Close();
}
}
Form1:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e){
// create an instance of Form2
var f2 = new Form2();
// add an event listener to SaveClicked event -which we have declared it in Form2
f2.SaveClicked += f2_SaveClicked;
f2.Show();
// or: f2.ShowDialog();
}
void f2_SaveClicked(object obj) {
// get data and use it here...
// any data which you pass in Form2.OnSaveClicked method, will be accessible here
}
}
UPDATE:
If you want to fire some events in form1, just after form2 closed, you can simply add a listener to Form2.FormClosed event:
// code from main form to create form2
private void button1_Click(object sender, EventArgs e) {
// Create a new instance of the Form2 class
Form2 settingsForm = new Form2();
settingsForm.FormClosed += SettingFormClosed;
// Show the settings form
settingsForm.Show();
string val = settingsForm.ReturnValue1;
MessageBox.Show(val);
}
void SettingFormClosed(object sender, FormClosedEventArgs e) {
// this method will be called automatically when form2 closed
}
here a sample how you can achieve this
//here I suppose that form1 is the mainform
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void UpdateMainForm(string updatedString)
{
//here you can update and invoke methods
//Once called you could raise events in your mainform
}
private void button1_Click(object sender, EventArgs e)
{
using (Form2 form2 = new Form2(this))
{
form2.ShowDialog();
}
}
}
Form2
public partial class Form2 : Form
{
private Form1 _mainForm1;
public Form2(Form1 mainForm1)
{
InitializeComponent();
_mainForm1 = mainForm1;
}
private void button1_Click(object sender, EventArgs e)
{
_mainForm1.UpdateMainForm( DateTime.Now.ToString());
}
}
I have a form that contains a Shockwave Flash object. I want that after playing the file or in the middle of it by pressing a key another form is shown. What should I do? Should I use an event?
Here's the code:
private void Form1_Load(object sender, EventArgs e)
{
axShockwaveFlash1.Movie = "c:/intro.swf";
axShockwaveFlash1.Forward();
axShockwaveFlash1.Play();
Form2 form2 = new Form2();
form2.Show();
}
And in Form2:
private void Form2_Load(object sender, EventArgs e)
{
Form1 form1 = new Form1();
form1.Close();
}
When I debug both forms are shown but I just want Form2.
You can pass the Form1 instance to the Form2 constructor, and close it there, like:
public Form2(Form1 form1)
{
InitializeComponents();
form1.Hide();//hide the control from the user, or close it if it not the main form..
}
Or if you want it to close the form1 instance when a button click then:
private Form1 _form1 = null;
public Form2(Form1 form1)
{
InitializeComponents();
_form1 = form1;
}
private void button1_Click(object sender, EventArgs e)
{
if (_form1 != null)
{
_form1.Hide();
}
}
Initialize the form2 in form1:
axShockwaveFlash1.Movie = "c:/intro.swf";
axShockwaveFlash1.Forward();
axShockwaveFlash1.Play();
Form2 form2 = new Form2(this);//"this here is the form1 instance itself"
form2.Show();
you can also use timer to check weather the movie is playing or not,if not then open new form which is form2
private void flash_Load(object sender, EventArgs e)
{
axShockwaveFlash1.Movie = #"C:\Users\Adil M\Documents\Visual Studio 2012\Projects\TProject\a.swf";
int a = axShockwaveFlash1.MovieData.Length;
timer1.Start();
}
now code on timer event
private void timer1_Tick(object sender, EventArgs e)
{
if (!axShockwaveFlash1.IsPlaying())
{
Fome2 fobj = new Form2();
this.Hide();
timer1.stop();
fobj.show();
}
else if(axShockwaveFlash1.IsPlaying())
{
}
}
this code is working for you only when your movie is complete or for any key you can also do it in timer
thanx