Problem to communicate between forms [modified]
-
Hi, I have a problem to pass some data between forms. Let's say I have 2 form, FormMain and FormChild, FormChild will be called from FormMain. What I want to do is simple. Whenever I change the textBox1's text in FormChild, the textBox1's text in FormMain will also contain the same text. After googling for a while, I got 2 solution : by using a delegate or directly instantiate FormMain in FormChild. Both solution unfortunately is in C#, so I need to convert it first. Well, I thought at first that there will be no problem at all to convert it, but that is just plain wrong. Both of the solution I get is just give me some error. Here is the converted source code 1.using delegate in Form Main.h :
#include "Form Child.h"
namespace Delegates {
public delegate void AddTextChangeDelegate(String^ item); public ref class FormMain : System::Windows::Forms::Form { public: FormMain() { formChild = gcnew FormChild(); } // declare as global variable private: FormChild^ formChild; private: System::Void button1\_Click(System::Object^ sender, System::EventArgs^ e) { formChild->AddTextChangeCallback = gcnew AddTextChangeDelegate(&this->AddTextChangeCallbackFn); formChild->Show(); } private: System::Void AddTextChangeCallbackFn(String^ str) { textBox1->Text = str; } };
}
in Form Child.h
namespace Delegates {
public ref class FormChild : System::Windows::Forms::Form { // declaring delegate, and get "error C2143: syntax error : missing ';' before '^' " // the compiler seems doesn't recognize this public: AddTextChangeDelegate^ AddTextChangeCallback; // user click add button and the delegate executed private: System::Void btnAdd\_Click(System::Object^ sender, System::EventArgs^ e) { AddTextChangeCallback(textBox1->Text ); } };
}
2. directly instantiate FormMain the solution I get (in C#) is just simply declare FormMain as a global variable in FormChild, then exposed the textBox in FormMain as a public. But when I do the same thing in C++, the compiler give an error "error C2143: syntax error : missing ';' before '^' ". so probably I just need to include the Form Main.h in Form Child.h, which give me another error "fatal error C1014: too many include files : depth = 1024" (is it because both form include each other's header?, so that is like making some cyclic dependency thing? I'm not sure why). After googling once more, I found that it is st
-
Hi, I have a problem to pass some data between forms. Let's say I have 2 form, FormMain and FormChild, FormChild will be called from FormMain. What I want to do is simple. Whenever I change the textBox1's text in FormChild, the textBox1's text in FormMain will also contain the same text. After googling for a while, I got 2 solution : by using a delegate or directly instantiate FormMain in FormChild. Both solution unfortunately is in C#, so I need to convert it first. Well, I thought at first that there will be no problem at all to convert it, but that is just plain wrong. Both of the solution I get is just give me some error. Here is the converted source code 1.using delegate in Form Main.h :
#include "Form Child.h"
namespace Delegates {
public delegate void AddTextChangeDelegate(String^ item); public ref class FormMain : System::Windows::Forms::Form { public: FormMain() { formChild = gcnew FormChild(); } // declare as global variable private: FormChild^ formChild; private: System::Void button1\_Click(System::Object^ sender, System::EventArgs^ e) { formChild->AddTextChangeCallback = gcnew AddTextChangeDelegate(&this->AddTextChangeCallbackFn); formChild->Show(); } private: System::Void AddTextChangeCallbackFn(String^ str) { textBox1->Text = str; } };
}
in Form Child.h
namespace Delegates {
public ref class FormChild : System::Windows::Forms::Form { // declaring delegate, and get "error C2143: syntax error : missing ';' before '^' " // the compiler seems doesn't recognize this public: AddTextChangeDelegate^ AddTextChangeCallback; // user click add button and the delegate executed private: System::Void btnAdd\_Click(System::Object^ sender, System::EventArgs^ e) { AddTextChangeCallback(textBox1->Text ); } };
}
2. directly instantiate FormMain the solution I get (in C#) is just simply declare FormMain as a global variable in FormChild, then exposed the textBox in FormMain as a public. But when I do the same thing in C++, the compiler give an error "error C2143: syntax error : missing ';' before '^' ". so probably I just need to include the Form Main.h in Form Child.h, which give me another error "fatal error C1014: too many include files : depth = 1024" (is it because both form include each other's header?, so that is like making some cyclic dependency thing? I'm not sure why). After googling once more, I found that it is st
roshihans wrote:
But then another problem comes out. The instance declared in Form Child.cpp is not the same instance as the previous FormMain
Because you are instantiating a new instance in the child form. You need to pass the main form's instance to child form (through constructor injection or some setter methods).
roshihans wrote:
So, what is the correct way to solve this problem?
I will stick with delegates. It is the best way to go.
roshihans wrote:
AddTextChangeCallback(textBox1->Text );
Don't call it blindly, your delegate instance may be
NULL
and you will end with null reference exception. Do a sanity check before you call it.System::Void btnAdd_Click(System::Object^ sender, System::EventArgs^ e)
{
if(AddTextChangeCallback != nullptr)
AddTextChangeCallback(textBox1->Text ); // Safe to call it now
}roshihans wrote:
// declaring delegate, and get "error C2143: syntax error : missing ';' before '^' " // the compiler seems doesn't recognize this
You might be doing it wrongly.
public ref class FormChild : System::Windows::Forms::Form
{
public:
delegate void AddTextChangeDelegate();
AddTextChangeDelegate^ AddTextChangeCallback;...........
};
:)
Navaneeth How to use google | Ask smart questions
-
roshihans wrote:
But then another problem comes out. The instance declared in Form Child.cpp is not the same instance as the previous FormMain
Because you are instantiating a new instance in the child form. You need to pass the main form's instance to child form (through constructor injection or some setter methods).
roshihans wrote:
So, what is the correct way to solve this problem?
I will stick with delegates. It is the best way to go.
roshihans wrote:
AddTextChangeCallback(textBox1->Text );
Don't call it blindly, your delegate instance may be
NULL
and you will end with null reference exception. Do a sanity check before you call it.System::Void btnAdd_Click(System::Object^ sender, System::EventArgs^ e)
{
if(AddTextChangeCallback != nullptr)
AddTextChangeCallback(textBox1->Text ); // Safe to call it now
}roshihans wrote:
// declaring delegate, and get "error C2143: syntax error : missing ';' before '^' " // the compiler seems doesn't recognize this
You might be doing it wrongly.
public ref class FormChild : System::Windows::Forms::Form
{
public:
delegate void AddTextChangeDelegate();
AddTextChangeDelegate^ AddTextChangeCallback;...........
};
:)
Navaneeth How to use google | Ask smart questions
Thanks for your quick reply, Navaneeth!! And now, the delegate thing is works perfectly!! I has been searching a lot about this in the internet without a result and now it's solved! Thanks a lot Navaneeth!! :thumbsup: I dunno if my question is beyond the topic, but can I ask about another thing? this is about the answers that Navaneeth wrote
N a v a n e e t h wrote:
Because you are instantiating a new instance in the child form. You need to pass the main form's instance to child form (through constructor injection or some setter methods).
constructor injection? I'm still a beginner in C++, so I'm barely hear about this. When you say constructor injection, is it something like dependency injection? I'm googling it in the internet, and this is that came up. Correct me if I was wrong, but from what I read in Internet, this dependency injection can be done using a container (??), created by third party developer (they mentioned something about pico container and others). It can not be done by .NET itself? I'm still confused :confused:
-
Thanks for your quick reply, Navaneeth!! And now, the delegate thing is works perfectly!! I has been searching a lot about this in the internet without a result and now it's solved! Thanks a lot Navaneeth!! :thumbsup: I dunno if my question is beyond the topic, but can I ask about another thing? this is about the answers that Navaneeth wrote
N a v a n e e t h wrote:
Because you are instantiating a new instance in the child form. You need to pass the main form's instance to child form (through constructor injection or some setter methods).
constructor injection? I'm still a beginner in C++, so I'm barely hear about this. When you say constructor injection, is it something like dependency injection? I'm googling it in the internet, and this is that came up. Correct me if I was wrong, but from what I read in Internet, this dependency injection can be done using a container (??), created by third party developer (they mentioned something about pico container and others). It can not be done by .NET itself? I'm still confused :confused:
roshihans wrote:
constructor injection?
By constructor injection, I meant to pass the first form's object to second form via constructor. Something like
Form2(Form1^ form1) // First form's object is injected through constructor
{
// keep the form1 object for future use
}As I said, go with delegates. It's the approaprite solution for your scenario. :)
Navaneeth How to use google | Ask smart questions
-
roshihans wrote:
constructor injection?
By constructor injection, I meant to pass the first form's object to second form via constructor. Something like
Form2(Form1^ form1) // First form's object is injected through constructor
{
// keep the form1 object for future use
}As I said, go with delegates. It's the approaprite solution for your scenario. :)
Navaneeth How to use google | Ask smart questions
N a v a n e e t h wrote:
By constructor injection, I meant to pass the first form's object to second form via constructor. Something like
Form2(Form1^ form1) // First form's object is injected through constructor
{
// keep the form1 object for future use
}But Form1 already include Form2.h (in my case Form1 act as a "parent" form, and instantiate Form2). So I think I can't declare Form2 (Form1^ form1) and keep the form1 object, like you have mentioned above, because I need to include Form1.h inside Form2.h, and that will give me this "fatal error C1014: too many include files : depth = 1024". Or maybe I don't need to include Form1.h inside Form2.h? Thanks
-
N a v a n e e t h wrote:
By constructor injection, I meant to pass the first form's object to second form via constructor. Something like
Form2(Form1^ form1) // First form's object is injected through constructor
{
// keep the form1 object for future use
}But Form1 already include Form2.h (in my case Form1 act as a "parent" form, and instantiate Form2). So I think I can't declare Form2 (Form1^ form1) and keep the form1 object, like you have mentioned above, because I need to include Form1.h inside Form2.h, and that will give me this "fatal error C1014: too many include files : depth = 1024". Or maybe I don't need to include Form1.h inside Form2.h? Thanks
roshihans wrote:
But Form1 already include Form2.h (in my case Form1 act as a "parent" form, and instantiate Form2). So I think I can't declare Form2 (Form1^ form1) and keep the form1 object, like you have mentioned above
Fair point! You will get circular dependency problems. To solve this, you need to have good understanding about C++ compiling and linking. You have to use forward declaration and declare parent form in child form's header file. Assume your parent form is named as
PForm
and child form asCForm
. Here is how yourPForm
's header file looks likepublic ref class PForm : public System::Windows::Forms::Form{
public:
void UpdateText(String^ str) // used to update the text box text. This will be called from CForm.
{
textBox1->Text = str;
}// your rest of code
};
Here is your
CForm
's headerref class PForm; // forward declaring PForm
public ref class CForm : public System::Windows::Forms::Form{
public:
CForm(PForm^ pf) // injecting dependency through constructor
{
InitializeComponent();
pForm = pf;
}private:
System::Void textBox1_TextChanged(System::Object^, System::EventArgs^);
PForm^ pForm; // Parent form's object used to update the control
};CForm.cpp
contains#include "CForm.h"
#include "PForm.h"System::Void CForm::textBox1_TextChanged(System::Object ^sender, System::EventArgs ^e){
if(pForm != nullptr)
pForm->UpdateText(textBox1->Text);
}You show the
CForm
fromPForm
likeCForm^ cForm = gcnew CForm(this);
cForm->Show();This should work fine. But if you use delegates, you can avoid all these and implementation will be pretty straight forward. So please stick with delegates unless you have a good reason to go with the above method. Hope it is clear now. :)
Navaneeth How to use google | Ask smart questions
-
roshihans wrote:
But Form1 already include Form2.h (in my case Form1 act as a "parent" form, and instantiate Form2). So I think I can't declare Form2 (Form1^ form1) and keep the form1 object, like you have mentioned above
Fair point! You will get circular dependency problems. To solve this, you need to have good understanding about C++ compiling and linking. You have to use forward declaration and declare parent form in child form's header file. Assume your parent form is named as
PForm
and child form asCForm
. Here is how yourPForm
's header file looks likepublic ref class PForm : public System::Windows::Forms::Form{
public:
void UpdateText(String^ str) // used to update the text box text. This will be called from CForm.
{
textBox1->Text = str;
}// your rest of code
};
Here is your
CForm
's headerref class PForm; // forward declaring PForm
public ref class CForm : public System::Windows::Forms::Form{
public:
CForm(PForm^ pf) // injecting dependency through constructor
{
InitializeComponent();
pForm = pf;
}private:
System::Void textBox1_TextChanged(System::Object^, System::EventArgs^);
PForm^ pForm; // Parent form's object used to update the control
};CForm.cpp
contains#include "CForm.h"
#include "PForm.h"System::Void CForm::textBox1_TextChanged(System::Object ^sender, System::EventArgs ^e){
if(pForm != nullptr)
pForm->UpdateText(textBox1->Text);
}You show the
CForm
fromPForm
likeCForm^ cForm = gcnew CForm(this);
cForm->Show();This should work fine. But if you use delegates, you can avoid all these and implementation will be pretty straight forward. So please stick with delegates unless you have a good reason to go with the above method. Hope it is clear now. :)
Navaneeth How to use google | Ask smart questions