Hello I have datagridview in form1 and through form1 I open form2 and through form2 I open form3 and string named vyber_ID_K placed in Form1 needs to be accessed in Form3 (I need to get its value in Form3)
this is placed on button click in form1
form2 a = new form2 ("Novy");
string vyber_IDK = (string)dataGridView1.CurrentRow.Cells["ID_K"].Value.ToString();
a.vyber_ID_K = vyber_IDK;
a.Show();
a.Closed += klient_Closed;
I would like to access vyber_ID_K in form 3, how it can be done? I tried to set public string vyber_ID_K in form2 and pass it similary to form3 but I get null. Am I doing it right? Is there any other better solution please?
Thanks in advance.
My step-by-step according to Servy:
button click in Form 1
Func vyberIDKGetter = () => dataGridView1.CurrentRow.Cells["ID_K"].Value.ToString();
try
{
form2 = new form2 ("Novy");
a.vyberIDKGetter = () => dataGridView1.CurrentRow.Cells["ID_K"].Value.ToString();
a.Show();
}
button click in form2
public Func vyberIDKGetter;
private void button1_Click(object sender, EventArgs e)
{
nova_platba b = new nova_platba("novy");
b.vyberIDKGetter();
b.Show();
b.Closed += klient_Closed;
}
In form3
Func<string> vyberIDKGetter = veberIDK;
string vyberIDK = vyberIDKGetter();
SqlCommand sc = new SqlCommand(#"
INSERT INTO kliplat (datum,text,castka,akce,subkey,priznak,rocnik)
VALUES (#datum,#text,#castka,#akce,#subkey,#priznak,#rocnik);
SELECT scope_identity();
", spojeni);
sc.Parameters.AddWithValue("#subkey", vyberIDK);
So the issue here is that the value that you want doesn't exist yet when you're constructing Form2, or even Form3 for that matter. It needs to have some means of accessing the data at some point in the future. We can get this behavior by leveraging delegates.
Rather than passing a string to Form2, when that form is constructed (since we don't know what the string will be yet) pass a Func<string>. That object will be a method that, when invoked, will provide a string that represents the needed value. Form1 can define it like this:
Func<string> vyberIDKGetter =
() => dataGridView1.CurrentRow.Cells["ID_K"].Value.ToString();
Then in Form3 when it's holding onto the function that was passed it can get the string out by simply invoking that delegate:
Func<string> vyberIDKGetter = [...];
string vyberIDK = vyberIDKGetter();
This approach to solving the problem is particularly adventageous in that Form3 doesn't need to know anything about Form1 or Form2. If there is some other caller that wants to use it they can provide their own delegate instead. If there is a developer handling the coding of each form they don't need to communicate all of the internal details of each form to each other, they can just handle the passing of this delegate and then be able to treat the caller/callee as a black box.
You have to make a public getter/setter around the string:
public string Vyber_ID_K
get
{
return vyber_ID_K;
}
set
{
vyber_ID_K = value
}
That you need a reference from Form 1 in Form 2, and from Form 2 in Form 3. So you can access
each Form.
You can't use a string as Referenced Parameter, becuase it is an immutable class. String C#
That is a really odd that you pass a parameter via the constructor
form2 a = new form2 ("Novy");
and in the same time you pass another parameter via the property
a.vyber_ID_K = vyber_IDK;
Why don't you instead pass all parameters via the constructor?
string vyber_IDK = (string)dataGridView1.CurrentRow.Cells["ID_K"].Value.ToString();
form2 a = new form2 ("Novy", vyber_IDK);
and in Form2
public class form2
{
private string Name { get; set; }
private int vyber_IDK { get; set; }
public form2( string Name, int vyber )
{
this.Name = Name;
this.vyber_IDK = vyber_IDK;
}
Then, passing anything to form3 from form2 works in the same way
form3 f = new form3( this.vyber_IDK );
Related
I have three forms, f1, f2, f3 we'll call them. I have a class Account, in which I store username, password, groups and path (files). F2 is the main form, and should interact with both other forms. F1 is the login form and F3 is the edit form. I use this in my program.cs to call the login form before other forms.
Form1 login = new Form1();
if (login.ShowDialog() == DialogResult.OK)
{
Application.Run(new Form2());
}
To pass data between f2 and f3, I use a constructor with the account class. However, I would also like to pass data from f1 to f2, but if I use the same approach, I get no data interaction between the forms (data is null).
I edited the above code to this:
Form1 login = new Form1();
Account acc = new Account();
if (login.ShowDialog() == DialogResult.OK)
{
Application.Run(new Form2(acc));
}
In the login form (f1), I pass some data to the Account class, so upon login button click this happens:
private void LoginButton_Click(object sender, EventArgs e)
{
Account acc = new Account();
//some code
acc.Groups = "New group";
//some more code
DialogResult = DialogResult.OK;
}
Then, in the Form2.cs, I have the following code:
string groups = "";
public Form2(Account acc)
{
InitializeComponent();
groups = acc.Groups;
}
But whenever I run it like that, I never get any results in the main form (f2), acc.Groups is always null, and I do not know why exactly. I used the same approach with constructors to pull data from f2 to f3, and it worked fine, why doesn't this work? Is it because I use the wrong approach with the login form? What is the correct way to handle this?
the problem is that you create a new instance of Account in the LoginButton_Click event. and you never pass this instance to the form2!
Create a field in the Form1 class of type Account:
Account my_account;
And overload the constructor to take an account as parameter:
public Form1(Account acc)
{
my_account = acc;
}
then reference in the click event the field my_account
private void LoginButton_Click(object sender, EventArgs e)
{
//reference the class variable
my_account.Groups = "New group";
//some more code
DialogResult = DialogResult.OK;
}
In the beginning you need to pass the starting instance of Account into the Form1 constructor so it can be filled with values:
Account acc = new Account();
Form1 login = new Form1(acc);
if (login.ShowDialog() == DialogResult.OK)
{
Application.Run(new Form2(acc));
}
Explanation in detail:
When creating an instance of Account acc = new Account(); you get a unique object with a specific location in the memory. When you pass this object to the constructor of Form1 and assign it to the private field my_account you actually pass only the reference of acc. Meaning that you pass the location of it in memory. That means that when you do this: my_account = acc; in the constructor you make sure that my_account points to the same location as the acc object. When you manipulate values of my_account by assigning a string to Groups you actually manipulate the original acc object. After returning from Form1 you pass the acc object again as reference to the next constructor. So when you access in Form2 this object in groups = acc.Groups; you access the original location in memory that you have manipulated and to which you have assigned the string "New group".
In your posted code you created in Form1 an entire new object using Account acc = new Account(); which is again unique and independent of the object that you created in the very beginning. This object also is located on a different portion of memory as the first acc object. This is why the property Groups is null when you have tried to access it in Form2
I hope this is understanable
I see you create new Account() in two places ( so you have more than one instance), but you don't pass account to form2 nowhere.
You can make Account static like Janes suggest in comment or make property to get account.
In Form1, declare
public Account Account { get; set; }
In Account, declare
public Form1 Form1{ get; set; }
After created 2 objects login and acc :
Form1 login = new Form1();
Account acc = new Account();
Assign to each other
login.Account = acc;
acc.Form1 = login;
I am developing an application where i have to get data from 2 different forms to fill different fields of same form
My Work
I have called the constructor of form1 from party form and from itemform with parameters
code form Itemform
string units = dr.Cells[2].Value.ToString();
string rate = dr.Cells[3].Value.ToString();
Form1 f1 = new Form1( units, rate);
this.Hide();
constructor on form1 called while debugging
public Form1(string units, string rate)
{
InitializeComponent();
ItemId_LBL.Text = units;
ItemName_TXT.Text = rate;
}
same for another form but i no want to close my main form1 and only close other forms while clicking button constructor called but fields not populated why
NOTE:
I HAVE TO FILL TEXTBOXES OF ALREADY OPENED FORM FORM1
from another form get object of opened form
Form1 f = (Application.OpenForms[0] as Form1);
f.PName_TXT.Text = name.ToString();
f.PId_LBL.Text = id.ToString();
}
If Form1 is already open, it means the constructor had already run. Make a setter method and call the method from other form.
public void UpdateUnitAndRate(string units, string rate)
{
ItemId_LBL.Text = units;
ItemName_TXT.Text = rate;
}
//put it in form2 (or itemform) as a field
Form1 f1;
//add this in the method or event (in itemform) you want to update units and rates in form1
if (f1 != null)
f1.UpdateUnitAndRate(units, rate);
else
f1 = new Form1(units, rate);
I think what you are looking for is Application.OpenForms, use this to create an instance of the open form and access the textbox.
I have a form, Form2 which contains a Hangman game (yes, it is the similar Hangman game to the one that i'm referring to in my previous question) and once the player finishes the game, the player will be brought to either one of two forms, Form4 and Form6 (one is a congratulations form for winning and one is a mocking/defeat form for losing) and in both forms Form4 and Form6, there is a label that displays the score that the player gets from the previous Form2.
I had placed a method to return the value of the score in Form2.
public int getScore()
{
return score;
}
And then in both forms, Form4 and Form6, there is these codes in each form respectively.
Form4
private void Form4_Load(object sender, EventArgs e)
{
Form2 game = new Form2();
lblFinalScore.Text += game.getScore().ToString();
}
Form6
private void Form6_Load(object sender, EventArgs e)
{
Form2 game = new Form2();
lblFinalScore.Text += game.getScore().ToString();
}
So after passing Form2 and playing the game, and when for example, I won the game and got 7 points, and Form4 appears, the lblFinalScore displays 0... WHY?!
Please help...
If you use the new keyword you create a new instance of the Form2 class.
This way you are using two different instances. Differnt instances are having data fields with different values.
If you want to access the same data field from any intances of a class, use the static keyword. You could store the score value in a static field, this way you could easily access it.
If you have a static field defined in a class, you can access the very field from any instance. However, using static fields are highly discouraged, since this violates basic OO principles.
Example:
class Program
{
static void Main(string[] args)
{
ExampleClass ex1 = new ExampleClass();
ExampleClass ex2 = new ExampleClass();
ex1.normalfield = "new value for ex1";
ex2.normalfield = "new value for ex2";
ExampleClass.staticfield = "static value";
Console.WriteLine(ex1.normalfield);
Console.WriteLine(ex2.normalfield);
Console.WriteLine(ExampleClass.staticfield);
}
class ExampleClass
{
public string normalfield = "";
public static string staticfield = "";
}
}
Passing the original instance of the Form could be a better way to go in your situation.
This could be done by storing a reference to the Form, or implementing the Singleton pattern.
However, the best solution in my opinion, would be to decouple the presentation of your game logic. You should be using a different class to implement the game logic and to store data values connected to the game and the form classes should be only responsible to present visually the current state of the object representing the state of your game.
You are creating two different instances of Form2. Refer to actual original instance of Form2.
Have class level variable on both Form4 and Form6 and set it from respective constructor. Pass instance from Form2.
Refer to Passing a value from one form to another.
I am trying to have a click event on a new form that gets the text property of controls in form1.
I have made a public method that returns the values that I need but the returned values are always null. I have looked everywhere for this.
Form1:
public List<string> returner()
{
List<string> thevalues = new List<string>();
thevalues.Add(textbox1.Text);
thevalues.Add(textbox2.Text);
return thevalues;
}
Form2:
Form1 x = new Form1();
List<string> values = x.returner();
label1.Text = values[0];
label2.Text = values[1];
My issue is that there are no values returned because Im declaring a new instance of Form1 rather than using the one that has values in it (I guess).
Yes, that would explain what's going wrong. Basically you need to tell Form2 about the relevant instance of Form1. Exactly how you do that will depend on what constructs everything. For example, you might have:
Form1 form1 = new Form1();
Form2 form2 = new Form2();
form2.Form1 = form1;
Or you could pass the reference in the constructor to Form2.
If those are really the names of your forms, by the way, I'd strongly advise you to rename them to something more meaningful - something which indicates the purpose of the form. Likewise returner not only violates .NET naming conventions, it also doesn't explain what it's doing.
you've messed up with your codes.. if you want to get a value of text just use this. string textValue = form1.textbox1.Text
or.. since you didnt post the full code here.. try this rather than creating the object form1.returner();
I have a main form that has most of the functionality in it. I was just wondering how would I pass on a variable from say a pop up form, to that main form.
Like for instance:
I have a main form that needs some connection info. So when you click the button "Enter Connection Info", it opens up a new form that the user can type in the IP Address he wants to use for his connection.
On this new form, I have a textbox and a button and once you enter the information it should close and pass on the string that contains the ip back to the original form.
Any suggestions? Do you think there is a better method of accomplishing this than using a windows form, and just going ahead and using a windows form or something? I'm quite perplexed on this issue at the moment.
Expose the textbox text as a public read only property. Show the connection form as a dialog and when it closes, get the connection from the property and then dispose the form:
in open form handler (button click, menu, whatever)
string connectionString = null;
using (ConnectionForm form = new ConnectionForm())
{
DialogResult result = form.ShowDialog();
if (result == DialogResult.Ok)
connectionString = form.ConnectionString
}
In you connection form:
public class ConnectionForm: Form
{
....
public string ConnectionString { get { return textBox1.Text; } }
}
You can create a public property in your main form and pass main form instance in pop-up constructor. In this way you can change the main form property.
You can also create an event in your pop-up form and hook it in your main form.
I like to use a pattern sort of like this (bear with me, c# is not my first language):
public class ValueForm: Form
{
public static string GetFromUser(string originalValue)
{
using (ConnectionForm form = new ConnectionForm())
{
form.TheValue = originalValue;
var result = form.ShowDialog();
if (result == DialogResult.Ok)
return form.TheValue;
else
return originalValue;
}
}
public string TheValue {
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
/* also some code behind your OK & cancel buttons to set
DialogResult appropriately,
and do any validation that you need to do
*/
}
and then you would use this like:
string newValue = ValueForm.GetFromUser(oldValue);
Reference Bind the controls on the dialog Form to properties of the Parent Form.
public dlgDbConnProps ( Form Owner )
{
// TODO: Complete member initialization
InitializeComponent ( );
owner = Owner;
}
private void cbo_ProviderLst_SelectedIndexChanged ( object sender, EventArgs e )
{
owner.Provider = cboLst.Text;
}
Here is another method that I have implemented:
... pass a Func to the child form constructor:
public dlgRequestLogin ( Func<string, string, bool> LoginMethod )
{
InitializeComponent ( );
p_loginMethod = LoginMethod;
}
... then handle on button click (or other appropriate event):
private void cmd_SendLoginCredentials_Click ( object sender, EventArgs e )
{
bool res = p_loginMethod.Invoke ( txt_UserID.Text, txt_UserPassword.Text );
}