Refreshing a previously called class's property - c#

Say, i have called a class in my mainform, like
BSPclass bsp = new BSPclass();
In that class there is 1 property like,
class BSPclass
{
public string p1 = "player1";
}
Then, if i click a button in mainform, a new form (as form2) will appear,
say, there is a textbox which will set a value for p1 (also BSPclass was called in form2 too)
private void save_Click(object sender, EventArgs e)
{
BSP.p1 = txtbox.text;
}
Now, problem is, if I close the form2, it doesn't show the neew value of p1 in mainform, still shows "player1"
How to refresh or do other anything?

It depends on where did you created BSP instance? If it's created in form2 then it's as well disposed along with the form. Both the instances are different here. You will have to pass it to main form using a delegate something like:
Say your main form have a insance of BSPclass like BSPclass bsp = new BSPclass();
In you form2 declare a delegate like
public delegate void passinfotomainform(string data);
Create a event of that delegate type
public event passinfotomainform datapassevent;
Then in button click raise the event
private void save_Click(object sender, EventArgs e)
{
BSP.p1 = txtbox.text;
if(datapassevent != null)
datapassevent(txtbox.text);
}
In main form, register this event like
form2.datapassevent += new EventHandler(myhandler);
In myhandler get the data
private void myhandler(string arg)
{
bsp.p1 = arg; //set the bsp in main form
}

You can simply pass the value of textbox to mainform and then refresh p1. You shouldn't create an instance of BSPClass in form2. See code below:
In form2:
public string pTemp;
private void save_Click(object sender, EventArgs e)
{
pTemp = txtbox.text;
}
In mainform:
BSPclass bsp = new BSPclass();
Form2 f=new Form2();
f.ShowDialog(this);
bsp.p=f.pTemp;

Related

Updating Form1 objects from Form2

I try to update Form1 values from Form2, but nothing happens. No errors also, strange...
Form1:
public static Form2 f2{ get; set; } = new Form2();
private void addButton1_Click(object sender, EventArgs e)
{
f2.Show();
}
Form2:
public void button1_Click(object sender, EventArgs e)
{
Form f1 = new Form();
f1.label2.ForeColor = Color.Red;
}
Nothing happens. I can get data to my form2 from form1, but I cannot send, I mean I can, but nothing happens... Why? Thank you
The other solutions mentioned here would work for your specific case, but I encourage you to look at the big picture, and design a generalized solution that will work for most cases.
Your problem essentially boils down to doing something on one form based on the events of another form.
The best approach to do this is, in my opinion:
Let Form1 do all its own actions.
Let Form2 do all its own actions.
If you need to do something on Form1 based on an event that occurred on Form2, let Form2 notify Form1 that something happened there, so go do your own thing.
If necessary, pass data from Form2 to Form1.
So I would make use of delegates for this purpose.
Imagine you have a Button and a Label on your Form1. Clicking the button opens up Form2, on which you have another Button. Clicking this button on Form2 should change the background color of the label on Form1. So our setup would look like this. You haven't mentioned if it's Winforms or WPF, so I'm using WPF for my convenience but the idea is the same in either.
Form1
Form2
In my Form1 I'd declare a public delegate with a signature like this:
public delegate void NotifyEvent();
That is, this delegate represents a method that takes in no parameters, and has void return type. The idea is to let Form2 'call' a method in Form1, and that method essentially notifies the button was clicked on Form2. So, if there was a way for us to call a method that resides in the Form1 from Form2, we can then notify Form1 of an event happening on Form2 With me so far?
Now, if I write a method like this in the Form1, and let it be called from Form2, that should accomplish our goal. Here, lblDisp is the Label in Form1.
public void ButtonClickedOnForm2()
{
lblDisp.Background = new SolidColorBrush(Colors.LawnGreen);
}
To accomplish this, I would define a delegate of type NotifyEvent in Form1 like below, and register the ButtonClickedOnForm2() method to it. Your Form1 code behind should look like this
public delegate void NotifyEvent();
public partial class Form1 : Window
{
public NotifyEvent notifyDelegate;
Form2 form2 = null;
public Form1()
{
InitializeComponent();
// This is 'registering' the ButtonClickedOnForm2 method to the delegate.
// So, when the delegate is invoked (called), this method gets executed.
notifyDelegate += new NotifyEvent(ButtonClickedOnForm2);
}
public void ButtonClickedOnForm2()
{
lblDisp.Background = new SolidColorBrush(Colors.LawnGreen);
}
private void BtnOpen_Click(object sender, RoutedEventArgs e)
{
// Passing the delegate to `Form2`
form2 = new Form2(notifyDelegate);
form2.Show();
}
}
Accordingly, now we need to modify our Form2. We need to tell us which delegate to invoke when the button click happens. So to do that, I'd pass the delegate in the constructor of Form2 like so:
public partial class Form2 : Window
{
NotifyEvent notifyDel;
public Form2(NotifyEvent notify)
{
InitializeComponent();
notifyDel = notify;
}
private void BtnOK_Click(object sender, RoutedEventArgs e)
{
// This invokes the delegate, which in turn calls the ButtonClickedOnForm2 method in Form1.
notifyDel.Invoke();
}
}
Now, when the button is clicked on Form2, it invokes the delegate. And on our Form1, we've told it that in case the delegate is invoked, it should go ahead and execute the ButtonClickedOnForm2 method. In that method, we've written code to change the background color of the label. And that should solve your problem.
Passing Data
Additionally, if you want to pass data from Form2 to Form1, you can simply add parameters to the delegate definition. Say you want to pass a string from Form2 to Form1. Then, you'd change your delegate to look like this:
public delegate void NotifyEvent(string data);
And the method ButtonClickedOnForm2 like so:
public void ButtonClickedOnForm2(string data)
{
lblDisp.Content = data;
lblDisp.Background = new SolidColorBrush(Colors.LawnGreen);
}
Then on Form2, invoke the delegate by passing a string like so:
private void BtnOK_Click(object sender, RoutedEventArgs e)
{
// This invokes the delegate, which in turn calls the ButtonClickedOnForm2 method in Form1.
notifyDel.Invoke("I am from Form2");
}
Now clicking the button on Form2 should change text and background color of label on Form1 like this:
With Form f1 = new Form(); you are creating a new form instead of accessing one which is already open and you don't call f1.Show(); therefore it will never be displayed. You need a reference to the one which is open. E.g. pass form 1 as constructor parameter to form 2.
In form 2:
public partial class Form2 : Form
{
private readonly Form1 _form1;
public Form2 (Form1 from1)
{
_form1 = form1;
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
_form1.label2.ForeColor = Color.Red;
}
}
In form 1:
// Cannot be static as we need a reference to `this`
private Form2 _f2;
public Form2 f2 {
get {
if (_f2 == null) {
_f2 = new Form2(this); // Pass form 1 as parameter to form 2.
}
return _f2;
}
}
private void addButton1_Click(object sender, EventArgs e)
{
f2.Show();
}
Thank you for constructor idea. Anyway (this) does not work for me in global scope. So I needed to simplify it to this:
Form 2 with constructor:
public Form1 _form1 { get; set; }
public Form2(Form1 form1)
{
_form1 = form1;
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
_form1.label2.ForeColor = Color.Red;
}
}
Form 1 creating new object with parameter everytime call needed(because of 'this'):
private void addButton1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2(this);
f2.Show();
}
Works fine so far...
try this code
Form1:
private void addbutton1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2(this);
f2.Show();
}
public void ColorChange()
{
label2.ForeColor = Color.Red;
}
Form2:
public Form1 f1;
public Form2(Form1 m)
{
this.f1 = m;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
f1.Show();
f1.ColorChange();
}

Can't call all methods from different Form

I have a problem with calling method from another class. Form1.cs contains:
public void RefreshTreeview()
{
MessageBox.Show("test");
this.treeView1.Nodes.Clear();
this.textBox10.Text = "test";
}
When I'm trying to call this method from another class "Form2.cs":
public void button2_Click(object sender, EventArgs e)
{
Form1 Obj = new Form1();
Obj.RefreshTreeview();
this.Close();
}
I'm receiving only message box with text. Treeview doesn't "clear" and textBox10 didn't dipslay "test". However when i'm trying to call the same method from method inside Form1 all elements were executed:
private void toolStripButton1_Click(object sender, EventArgs e)
{
RefreshTreeview();
}
Of course both classes are public. Please help.
Regards
I would suggest to retrieve the same Form1 instance which is probably the one you are actually seeing on the screen.
public void button2_Click(object sender, EventArgs e)
{
Form1 Obj = // retrieve instead of create a new one
Obj.RefreshTreeview();
this.Close();
}
To retrieve the Form1 instance there are multiple ways please leave a comment if required.
If you want to create a new instance of the Form1 and then clear it you have to use Show() method. E.g.:
public void button2_Click(object sender, EventArgs e)
{
Form1 f = new Form1();
f.RefreshTreeview();
f.Show();
}
But I assume your aim is to clear already existing form. Easiest way is to inform the Form2 who is its owner. Then you can access the owner from the Form2.
So in the method you use to invoke Form2 from Form1, instead of using Show() method use Show(this) - this way you pass current instance as the owner of the new dialog.
Code in Form1, where you invoke Form2:
Form2 f2 = new Form2();
f2.Show(this); // Current window is now the owner of the Form2
And now on the Form2 you can do your thing with accessing Form1, removing Nodes and setting text:
private void button1_Click(object sender, EventArgs e)
{
if (this.Owner == null) return; // Sanity check if there is no owner.
Form1 f = (Form1)this.Owner; // Get the current instance of the owner.
f.RefreshTreeview();
f.Show();
}

Switching between two Windows forms

I am working on a game that utilizes Windows Forms in C#. I want to be able to use the first form to call a second form. I have this working. Then I would like for the second form to send data back to the first form rather than creating a new instance of the first form. Can this be done? I know I need to have my properties set up so that I can set the variables from one form to the other. I am just not sure how to go about calling the first form without creating a new instance of it.
Is there a way that this can be done?
For example if I have Form A create an instance of Form B, can I have Form B do some work and send the data back to the original Form A without creating a new instance of Form A?
If you don't use the Data sent back Form A right away then you could use the Form_Closing event handler Form B and then a public property in Form B also.
In your Form A it could look like this:
public partial class FormA : Form
{
FormB frmB = new FormB(); // Instantiate FormB so that you could create an event handler in the constructor
public FormA()
{
InitializeComponent();
// Event Handler for Form Closing
frmB.FormClosing += new FormClosingEventHandler(frmB_FormClosing);
}
void frmB_FormClosing(object sender, FormClosingEventArgs e)
{
String fromFormB = frm2.FormBData; // Get Data from Form B when form is about to close
}
private void button1_Click(object sender, EventArgs e)
{
frmB.ShowDialog(); // Showing Form B
}
}
And in your Form B it could look like this:
private void button1_Click(object sender, EventArgs e)
{
// Let just say that the data is sent back once you click a button
FormBData = "Hello World!";
Close();
}
public String FormBData { get; set; }
It's hard to say without knowing your full requirements. But generally I go like this (Somewhat psuedo code).
Form2 dialogForm = new Form2();
if(dialogForm.ShowDialog() == DialogResult.OK)
{
this.PropertyOnForm1 = dialogForm.PropertyOnForm2
}
This ofcourse relies that your second form is a dialog. You will need to set the dialogresult buttons on Form2, and have a public property that will be accessed from Form1 once the dialog has been completed.
Let me know if this doesn't work and I'll write up a different answer.
Since you are creating Form2 in Form1, you can create a custom event in Form2 and subscribe to it in Form1 at the time that you create Form2, if you are returning information from Form2 when you are closing it then Edper's or MindingData's answers will work.
Here is a quick and dirty example using EventHandler<TEventArgs>
Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.myCustomEvent += frm2_myCustomEvent;
frm2.Show();
}
void frm2_myCustomEvent(object sender, string e)
{
this.Text = e;
}
}
Form2
public partial class Form2 : Form
{
public event EventHandler<string> myCustomEvent;
int count;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
count +=1;
myCustomEvent(sender, count.ToString());
}
}

How to pass the value from one form to another one?

I have a MainForm and AnotherForm. AnotherForm is accessed via MainForm's menuItem.
AnotherForm has listView. When user clicks on an item it I want to get the string element and pass it to MainForm's textbox, so the element shows there and AnotherForm is closed. So far AnotherForm closes but nothing shows in the textbox in MainForm. Any suggestions?
private void listView1_ItemActivate(object sender, EventArgs e)
{
string input = listView1.SelectedItem[0].ToString();
MainForm mainF = new MainForm(input);// called the constructor
this.Close(); //close this form and pass the input to MainForm
mainF.inputTextBox.Text = input;
mainF.loadThis(input);
}
I assume you have an instance of MainForm already, and that's what creates an instance of AnotherForm.
Inside the event you posted, you're actually creating an entirely new instance of MainForm, never showing it, and then it's destroyed anyway when AnotherForm closes.
The reason you see nothing in the text box is because you're looking at the original instance of MainForm, which you haven't actually changed.
One quickie way of fixing this would be passing a reference to the original MainForm into AnotherForm:
public class AnotherForm
{
private MainForm mainF;
public AnotherForm(MainForm mainF)
{
this.mainF = mainF;
}
...
...
private void listView1_ItemActivate(object sender, EventArgs e)
{
...
mainF.inputTextBox.Text = input;
...
}
}
Note: Instead of having AnotherForm aware of MainForm, you might want to switch it around and create a public property in AnotherForm like this:
public class AnotherForm
{
public InputValue { get; private set; }
private void listView1_ItemActivate(object sender, EventArgs e)
{
...
InputValue = input;
...
}
}
Which you can then access from MainForm when the other form is closed:
private void SomeMethodInMainForm()
{
var newAnotherForm = new AnotherForm();
newAnotherForm.ShowDialog();
var inputValueFromAnotherForm = newAnotherForm.InputValue;
// do something with the input value from "AnotherForm"
}
If your MainForm has already been created you cannot just create another one in order to access it and set properties. You've created two separate MainForms (though the 2nd one is hidden because you never showed it).
It sounds like what you want to do is a modal dialog pattern. Your MainForm is the main window in your application. You want to have a 2nd form pop up when you click on a menu link. This is called a dialog. Then when you close that dialog you want your MainForm to retrieve a value as a returned result of the dialog.
In your MainForm the event handler which handles the menu item click should look something like this:
private void pickSomethingMenuItem_Click(object sender, EventArgs e)
{
using (var picker = new PickerDialog())
{
if (picker.ShowDialog(this) == DialogResult.OK)
{
LoadSomething(picker.SomethingPicked);
}
}
}
Then the following code would be inside your dialog form:
public string SomethingPicked { get; private set; }
private void somethingListView_ItemActivate(object sender, EventArgs e)
{
SomethingPicked = somethingListView.SelectedItem[0].ToString();
DialogResult = DialogResult.OK;
}
Notice how I named all of the objects with meaningful names. Well, except for "Something". It was impossible to tell from your code what you were actually using the dialog to pick. You should always use meaningful names for your objects and variables. Your code is almost completely nonsensical.
And you should almost never make a control on a Form public like you have with your inputTextBox. You should always expose values you want to share as public properties.
On this presented solution, you could do five main things in order to achieve what you want to do, namely:
1) Declare a global object for AnotherForm in MainForm
2) Initiate a FromClosing event handler for AnotherForm in MainForm
3) Make a public property or field in AnotherForm
4) Before closing in AnotherForm you save it the public property mentioned above
5) In the MainForm get the public property from AnotherForm
Here is the code:
MainForm
public partial class MainForm : Form
{
AnotherForm anotherForm; // Declare a global object for AnotherForm
public MainForm()
{
InitializeComponent();
}
private void showToolStripMenuItem_Click(object sender, EventArgs e)
{
anotherForm = new AnotherForm(); // when Menu Item is clicked instantiate the Form
anotherForm.FormClosing += new FormClosingEventHandler(anotherForm_FormClosing); // Add a FormClosing event Handler
anotherForm.ShowDialog();
}
void anotherForm_FormClosing(object sender, FormClosingEventArgs e)
{
inputTextBox.Text = anotherForm.listViewValue; // get the Value from public property in AnotherForm
}
}
AnotherForm
void listView1_ItemActivate(object sender, EventArgs e)
{
listViewValue = listView1.SelectedItems[0].Text; // Get the listViewItem value and save to public property
this.Close(); // Close
}
public String listViewValue { get; set; } // public property to store the ListView value
One thing to note here in comparison to your code I didn't use ToString() in ListView.SelectedItems:
listView1.SelectedItems[0].ToString();
But instead use the Text Property:
listView1.SelectedItems[0].Text;

Get data back to the original form from a second form

I have two forms, and I create the second by using:
Form2 f2 = new Form2();
f2.Show();
Form2 has a variable that is public and changes every mousemove. I have a button on that form which, when press, saves the variable. Now the problem is that I don't know how to pass it back to Form1.
You should use events. Form2 should define an event that is triggered as appropriate (it sounds like that should be when the button is clicked). Form1 can then subscribe to that event and do...whatever with it.
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public event Action<string> MyEvent; //TODO give better name and set arguments for the Action
private void button1_Click(object sender, EventArgs e)
{
string someValue = "Hello World!"; //TODO get value that you want to share
if (MyEvent != null)
{
MyEvent(someValue);
}
}
}
And then in your main form:
private void button1_Click(object sender, EventArgs e)
{
Form2 otherForm = new Form2();
//subscribe to the event. You could use a real method here, rather than an anonymous one, but I prefer doing it this way.
otherForm.MyEvent += value =>
{
//do other stuff with "value".
label1.Text = value;
};
otherForm.Show();
}

Categories

Resources