C# call function from outside current class - c#

Currently have a mainForm.cs which calls a class panel.cs
panel.cs holds multiple pictureboxes with events such as _click, _mousedown, _mouseup
I wish to call a function in mainForm.cs from panel.cs
do i need to use a callback / delegate. Is there another way to access this function
I have tried
Main main = new Main();
main.functioninMain does not work
any help or direction would be appreciated.
for example
panel.cs
private void pb_button1_Click(object sender, EventArgs e)
{
this.BeginInvoke(new Action(main.functioninMain));
}

You should not instantiate another object of MainForm, which creates a duplicate and all the objects withing the new MainForm will not have the values of your actual MainForm.
Approach 1
You can try creating a static instance of you MainForm like below
public partial class MainForm : Form
{
public static MainForm Instance = null;
public MainForm()
{
InitializeComponent();
Instance = this;
}
public SomeMethod()
{
}
}
Now if you have your panel class, then you can easily access public methods and variables of MainClass
class Panel : Form
{
public Panel()
{
MainForm.Instance.SomeMethod();
}
}
Edit: Pass Handle as parameter to the form (From Ben Voigt's suggestion)
Approach 2:
As Ben suggested, it is also important to have a safer code, so much cleaner approach will be passing handle of the control as parameter and then to access them.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
TestClass test = new TestClass();
test.ModifyText(textBox1);
}
}
public class TestClass
{
public void ModifyText(TextBox textBox)
{
textBox.Text = "New text";
}
}

If we can use delegate & events something like this
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Panel formPanel = new Panel();
formPanel.OnPanelClick += new Panel.OnPanelButtonClick(formPanel_OnPanelClick);
formPanel.Show();
}
void formPanel_OnPanelClick(string a)
{
MessageBox.Show(a);
}
}
public partial class Panel : Form
{
public delegate void OnPanelButtonClick(string a);
public event OnPanelButtonClick OnPanelClick = null;
public Panel()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (OnPanelClick != null)
{
OnPanelClick("from Panel.cs");
}
}
}

You should avoid circular dependencies at all costs (class A depends on class B, and class B depends on Class A).
There are so many ways to do this, but perhaps one of the easier ways is to use an interface. mainForm.cs implements it like this:
public class mainForm : IMainForm {
// This method is defined in the interface, so mainForm
// must implement it.
public string GetStringFromMainForm() {
return "Hello from MainForm";
}
public void CreatePanel() {
// pass in a reference to myself so panel knows how to
// talk to me.
var panel = new Panel(this);
}
}
And IMainForm (the interface) could look like this:
public interface IMainForm {
string GetStringFromMainForm();
}
Then your panel class can talk to the Main form without having to reference mainForm.cs explicitly:
public class Panel {
// use a private variable to keep track of main form
private IMainForm _mainForm;
// Constructor: pass in a class that implements IMainForm. It isn't
// a type of MainForm, so there's no dependency on the concrete class.
public Panel(IMainForm mainForm) {
_mainForm = mainForm;
}
public void TalkToMainForm() {
var resultFromMainForm = _mainForm.GetStringFromMainForm();
Console.WriteLine(resultFromMainForm);
}
}

Related

Calling a function in the main Form from another Class in C#

how I can call a function located in the Form class from another class?
this is my code.I want call get_data(data) in prog class?
thanks.
public partial class Form1 : Form
{
get_data(int mydata)
{
//code
}
//code
prog var1=new prog();
var1.start_data();
}
public class prog
{
public void start_data()
{
Thread ct=new Thread(do);
ct.start();
}
private void do()
{
int data=40;
get_data(data); ///?????????????this is wrog
}
}
If you need to access the current instance of your main form, you could pass it along to the class:
public partial class Form1 : Form
{
internal void get_data(int mydata)//Change to internal or public, as default is private
{
//code
}
private void button1_Click(object sender, EventArgs e)
{
prog var1 = new prog();
var1.start_data(this);//pass along instance of your main form
}
}
public class prog
{
private Form1 MainForm;
public void start_data(Form1 form)
{
MainForm = form;//set form
Thread ct = new Thread(doSmt);
ct.Start();
}
private void doSmt()
{
int data = 40;
MainForm.get_data(data); //use form
}
}
Before you can call a method from another class you need an instance of this class. One way would be to create a new instance.
But I guess you'll have an instance of this class already because it's a form an I guess you are opening this form anywhere; just use this instance.
A hint: I would not put any business logic in my form. I would put it in another class.
private void do()
{
int data=40;
Form1 form = new Form1();
form.get_data(data);
}
Don't forget to make the get_data method public because you can't access it in another class when it's private.
The method is not static so you need to actually instantiate the Form1 class.

Accessing MainForm from another class file

I have this MainForm class:
namespace homework_001{
public partial class MainForm : Form
{
public MainForm()
{InitializeComponent();}
public string Change
{
get{ return label.Text;}
set{ label.Text = value;}
}
void ButtonClick(object sender, EventArgs e)
{
Test a = new Test();
a.changer();
}
}}
And I have this class:
namespace homework_001{
public class Test
{
private MainForm form = new MainForm ();
public void changer(){
form.Change = "qqqqq!";
}
}}
Desired workflow is to change the label/text on button press.
It compiles, but nothing happens after I press the button.
What might be the issue?
What is happening is that the form you are showing is not the same as the one inside the class Test.
To make things work you should pass the form to the class Test in this way:
public class Test
{
private MainForm form;
public Test(MainForm f)
{
this.form=f;
}
public void changer(){
form.Change = "qqqqq!";
}
}}
and in your main form you do this:
public partial class MainForm : Form
{
public MainForm()
{InitializeComponent();}
public string Change
{
get{ return label.Text;}
set{ label.Text = value;}
}
void ButtonClick(object sender, EventArgs e)
{
Test a = new Test(this);
a.changer();
}
}}
done create a new object of the main form.. Instead. make the string Change public and static
and change it from test class like Mainform.Change="some text";
You're creating another MainForm object, different from the one that's actually displayed on the screen. To work on the same object you need to pass it to the Test class, like this:
Test a = new Test(this); // "this" is the MainForm object you want to work with
a.changer();
This will give Test class a reference to your MainForm object.
Now, you need to create a constructor in Test with one argument, and store the received reference to your form object in Test's private MainForm form field. You shouldn't have any trouble doing that.
change you code below:
void ButtonClick(object sender, EventArgs e)
{
Test a = new Test();
a.changer(ref this);
}
you pass the form object to function by refrence and changed that
public class Test
{
public void changer(ref MainForm form){
form.Change = "qqqqq!";
}
}
refer this link Passing Reference-Type Parameters (C# Programming Guide)

No errors, label seems like it should change to the indicated text but its not

Can anybody tell me why this is doing nothing? pcNameLabel.Text is supposed to be changing to bob when StatTransfer() is called by FighterButtonClick. According to the debugger everything is working right.
I've taken out some extra variables and stuff unrelated to the problem at hand.
public partial class MainForm : Form
{
public static string VariableLabel1;
public static string Variable2;
Random _r = new Random();
public MainForm()
{
InitializeComponent();
}
void CLoop()
{
while(true)
{
SetInfo();
}
}
public void SetInfo()
{
this.pcNameLabel.Text = VariableLabel1;
}
void ChClassButtClick(object sender, EventArgs e)
{
CharStats form = new CharStats();
form.Show();
}
}
This is a seperate windows form window.
public partial class CharStats : Form
{
public CharStats()
{
InitializeComponent();
}
void StatTransfer()
{
MainForm Mform = new MainForm();
MainForm.VariableLabel1 = "Bob";
Mform.SetInfo();
}
void FighterButtonClick(object sender, EventArgs e)
{
Fighter();
StatTransfer();
}
}
In these lines
void StatTransfer()
{
// This is a new instance of MainForm, not the original one
MainForm Mform = new MainForm();
MainForm.VariableLabel1 = "Bob";
Mform.SetInfo();
}
you create a new instance of MainForm and this instance is never displayed. This hidden instance contains the label that you are trying to change, but you cant't see it.
The simplest workaround to the problem is to pass the calling instance of MainForm to CharStats form when you initialize it
void ChClassButtClick(object sender, EventArgs e)
{
CharStats form = new CharStats(this);
form.Show();
}
Now you should change the constructor of CharStats to receive the passed instance and save it in a global variable inside the CharStats class
public partial class CharStats : Form
{
private MainForm _callingForm;
public CharStats(MainForm callingForm)
{
InitializeComponent();
_callingForm = callingForm;
}
.....
And use this saved instance where you need it
void StatTransfer()
{
_callingForm.VariableLabel1 = "Bob";
callingForm.SetInfo();
}
}
EDIT By the way, you dnn't need to use static variable for this to work. Simply change the method MainForm.SetInfo to receive a string and pass Bob when you call it
public void SetInfo(string newText)
{
this.pcNameLabel.Text = newText;
}
From CharStats
void StatTransfer()
{
callingForm.SetInfo("Bob");
}
MainForm is not set to display anywhere. I believe you want to add it to your CharStats form like so:
void StatTransfer()
{
MainForm Mform = new MainForm();
MainForm.VariableLabel1 = "Bob";
Mform.SetInfo();
this.Controls.Add(Mform);
}

Accessing Form's Control from another class C#

I'm a newbie in c# and visual studio, but not programming in general.
I searched for answer to my question for 3 days and I found plenty of them, but for some weird reason (I'm sure I'm missing something very obvious) I cannot get it to work.
I think it's the most basic question newbies like me ask.
I have a form (Form3) with a text box and a button (I set it up is just for testing purposes).
I want to populate and read this text box from another class. I understand the most proper way to do this is to create a property in Form3.cs with GET and SET accessors. I did that but I cannot get it to work. I'm not getting any error messages, but I'm not able to set the value of the text box either. It just remains blank.
Here's my sample code:
namespace WindowsFormsApplication1
{
public partial class Form3 : Form
{
public string setCodes
{
get { return test1.Text; }
set { test1.Text = value; }
}
public Form3()
{
InitializeComponent();
}
private void Form3_Load(object sender, EventArgs e)
{ }
private void button1_Click(object sender, EventArgs e)
{
a.b();
}
}
public class a
{
public static void b()
{
Form3 v = new Form3();
v.setCodes = "abc123";
}
}
}
Can someone lend me a hand solving this?
The problem is you are setting the value to a new instance of the form. Try something like this:
public partial class Form3 : Form {
public string setCodes
{
get { return test1.Text; }
set { test1.Text = value; }
}
private A a;
public Form3()
{
InitializeComponent();
a = new A(this);
}
private void button1_Click(object sender, EventArgs e)
{
a.b();
}
private void Form3_Load(object sender, EventArgs e)
{
}
}
public class A
{
private Form3 v;
public a(Form3 v)
{
this.v = v;
}
public void b()
{
v.setCodes = "abc123";
}
}
You're creating a brand new Form3() instance.
This does not affect the existing form.
You need to pass the form as a parameter to the method.
Try this:
public partial class Form3 : Form
{
/* Code from question unchanged until `button1_Click` */
private void button1_Click(object sender, EventArgs e)
{
a.b(this);
}
}
public class a
{
public static void b(Form3 form3)
{
form3.setCodes = "abc123";
}
}
This passes the current instance of the form to the other class so that it can update the setCodes property. Previously you were creating a new form instance rather than updating the current form.
Sending form instance to other other class
Form1 objForm1=new Form1();
obj.Validate(objForm1);
Easy way to access controls in another class by modifying Controls Private to Public in the Form(Designer.cs)

C# How to access setter method on main form, from my user control?

I have a UserControl, that contains a panel, the panel contains a picture box.
When I MouseMove over the Picture Box, I want to update a label on the MainForm.
I have a get/set method on the main form, but how do I use it?? thanks
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
public String MouseCords
{
get { return this.MouseCordsDisplayLabel.Text; }
set { this.MouseCordsDisplayLabel.Text = value; }
}
}
public partial class ScoreUserControl : UserControl
{
public ScoreUserControl()
{
InitializeComponent();
}
private void ScorePictureBox_MouseMove(object sender, MouseEventArgs e)
{
// MainForm.MouseCords("Hello"); //What goes here?
}
}
Actually it's possible to do in your case like:
((MainForm)this.ParentForm).MouseCords = "Some Value Here";
But the right way is with events like Felice Pollano mentinoed:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
this.myCustomControlInstanse.PicureBoxMouseMove += new EventHandler<StringEventArgs>(myCustomControlInstanse_PicureBoxMouseMove);
}
private void myCustomControlInstanse_PicureBoxMouseMove(object sender, StringEventArgs e)
{
this.MouseCordsDisplayLabel = e.Value // here is your value
}
}
public class StringEventArgs : EventArgs
{
public string Value { get; set; }
}
public partial class ScoreUserControl : UserControl
{
public event EventHandler<StringEventArgs> PicureBoxMouseMove;
public void OnPicureBoxMouseMove(String value)
{
if (this.PicureBoxMouseMove != null)
this.PicureBoxMouseMove(this, new StringEventArgs { Value = value });
}
public ScoreUserControl()
{
InitializeComponent();
}
private void ScorePictureBox_MouseMove(object sender, MouseEventArgs e)
{
this.OnPicureBoxMouseMove("Some Text Here");
}
}
Ideally, you should raise an event for the same.
Create a delegate
public delegate void Update();
in the user control
public class MyUserControl : UserControl
{
public event Update OnUpdate;
}
On the main form register a handler for the user controls event.
public class Main
{
public Main()
{
myUserControl.OnUpdate += new Update(this.UpdateHandler);
}
void UpdateHandler()
{
//you can set the delegate with sm arguments
//set a property here
}
}
On user control,
To raise an event on button click
do this
OnUpdate();
This might give you an idea...
public partial class ScoreUserControl : UserControl
{
public ScoreUserControl()
{
InitializeComponent();
}
private void ScorePictureBox_MouseMove(object sender, MouseEventArgs e)
{
// MainForm.MouseCords("Hello"); //What goes here?
MainForm parent = this.ParentForm as MainForm;
if (parent != null) parent.MouseCordsDisplayLabel.Text = "Hello";
}
}
You have several options:
Create an event on the user control and have to form listen to it (I think this is the recommended way by most C# programmers).
Pass a reference to the main form to the User Control (in the constructor). This way, the user control knows about its MainForm.
Cast this.ParentForm to the MainForm class, then you have the reference.
Options 2 and 3 are somewhat more comfortable and lazy, but the cost is that the user control has to know about the specific class MainForm. The first option has the advantage that you could reuse the user control in another project, because it does not know about the MainForm class.
You should publish an event from the user control and subscribe to it from the main form.
At least this is the pattern suggested for winform. In any case the idea is to make the control "observable" from the agents who need to see the coords, instead of using it as a driver to update the interested agents.

Categories

Resources