Send parametny from one form to another in C # - c#

I have two forms (C#). In one form, there is a method that takes data and stores them in a database after closing the form that I want to be on the other (the main form) to update the data. How to do it using OOP or simply to make the most beautiful and well.

Generally, when you want to let main form to be updated, you create a public method on that form and call it from the other form when it has the new data and can send them to main form. It shouldn't be a problem.
Note that if you want to send data to somewhere, you need a reference to that place, i.e. you need a reference to main form in the other form. Either pass this from main form to the constructor of the other form, or you can also store the reference in a static field in Program class (do it in Main method where you create the main form) etc.

The most OOP-friendly solution would probably be to have an event on whichever form "triggers" a data update, that is subscribed to and handled by another form's method. Here's a basic wire-up:
public class Form1:Form
{
public event EventHandler<MyDataObject> DataChanged;
...
public override void OnClosing(CancelEventArgs e)
{
//Put in logic to determine whether we should fire the DataChanged event
try
{
if(DataChanged != null) DataChanged(this, myFormCurrentData);
base.OnClosing(e);
}
catch(Exception ex)
{
//If any handlers failed, cancel closing the window until the errors
//are resolved.
MessageBox.Show(ex.Message, "Error While Saving", MessageBoxButtons.OK);
e.Cancel = true;
}
}
}
...
public class Form2:Form
{
//Called from wherever you would open Form1 from Form2
public void LaunchForm1()
{
var form1 = new Form1();
form1.DataChanged += HandleDataChange;
form1.Show();
}
private void HandleDataChange(object sender, MyDataObject dataObj)
{
//Do your data validation or persistence in this method; if it fails,
//throw a descriptive exception, which will prevent Form1 from closing.
}
}
You don't have to use an event; a simple delegate could be used as well and it would do pretty much the same thing, while also being able to be specified in the form's constructor (thus requiring the handler to be provided).

You can do something like this for updating the values in one form from another form...
Form 2 code
public event EventHandler<UpdatedEventArgs> updateEvent;
public class UpdatedEventArgs : EventArgs
{
public string SomeVal { get; set; } // create custom event arg for your need
}
protected virtual void OnFirstUpdateEvent(UpdatedEventArgs e)
{
if (updateEvent != null)
updateEvent(this, e);
}
private void button1_Click(object sender, EventArgs e)
{
UpdatedEventArgs eventData = new UpdatedEventArgs();
eventData.SomeVal = "test"; // set update event arguments, according to your need
OnFirstUpdateEvent(eventData);
}
public Form2()
{
InitializeComponent();
}
Form 1 code
public Form1()
{
InitializeComponent();
Form2 form2 = new Form2();
form2.updateEvent += new EventHandler<Form2.UpdatedEventArgs>(form2_updateEvent); // create event handler to update form 1 from form 2
form2.Show();
}
void form2_updateEvent(object sender, Form2.UpdatedEventArgs e)
{
if (e != null && e.SomeVal != null)
{
// Do the update on Form 1
// depend on your event arguments update the grid
//MessageBox.Show(e.SomeVal);
}
}

Related

Accessors (Properties) without Form.ShowDialog()

I am trying to set a ConstantLine for a DevExpress SplineChart that is created in the Form1 from Form2 and also set a numericalupdown.value placed in the Form2 for a textBox.text that is placed in the Form1, whilst both Form1 and Form2 are Open and running.
I am using from accessors {get;set;} to get and set values of DevExpressChart as i have written down in my codes.
I can get the values, but i can't set any value without using Form1.ShowDialog().
I have also used Form1.Update(); andForm1.Refresh(); but the mentioned code only run successfully with the use of Form1.Show(); or Form1.ShowDialog();
However, i want them to execute while both forms are running Form2 as a child of Form1 an seeing the changes in the Form1
Code
//Code Snippet in the Form2:
//NumericalUpDown-ValueChanged Event: In Form2
private void numUpDnShkgTimeRstcConfig_ValueChanged(object sender, EventArgs e)
{
Form1 frm1 = new Form1();
if (chkBxShakingTimeRestCteLineConfig.Checked == true)
{
XYDiagram diagram = (XYDiagram)Frm1.SplineChart.Diagram;
diagram.AxisX.ConstantLines.Add(new ConstantLine("Shaking Time", Convert.ToString(numUpDnShkgTimeRstcConfig.Value)));
Frm1.TxtBx = Convert.ToString(numUpDnShkgTimeRstcConfig.Value);
}
}
//Code Snippet in the Form1
//Pass Objects And Parameter.
public DevExpress.XtraCharts.ChartControl SplineChart
{
get {return SplineChrt1Form1; }
set { SplineChrt1MainFrm = value; }
}
public string TxtBx
{
get { return txtBxSmplWt1Form1.Text; }
set { txtBxSmplWt1Form1.Text = value; }
}
...
The way I understood your problem was that:
You are displaying a Chart in Form1.
From Form1, you want to show a second form (Form2) that allows you to change or specify values for the Chart in Form1.
You want to get the updated values from Form2 in to Form1.
The best way to setup this sort of notification and updating of a parent form from a child form is to use Events. Events enable a child form to notify its parent without actually knowing anything about the parent.
Step 1 - Create an EventArgs class. This class will be used to hold the information you want to pass from Form2 to Form1.
Generally speaking, I find it is better to have the properties as Read Only and only set them in the constructor for this sort of event.
// I wasn't sure what the parameters were called or their type,
// so I just used an int and string to demonstrate the functionality
public class ChartValuesChangedEventArgs : EventArgs
{
public ChartValuesChangedEventArgs (int value1, string value2)
{
Value1 = value1;
Value2 = value2;
}
public int Value1 { get; private set; }
public string Value2 { get; private set; }
}
Step 2 - Declare the event that will be raised from Form2. This is what will notify the Parent (Form1) that the values have changed and what the values are.
public event EventHandler<ChartValuesChangedEventArgs> ValuesChanged;
Step 3 - Raise the Event. This is where you notify the Parent that the values have changed.
For this example, I am raising the event on a Button Click. You can just as easily put the content of this function in your own numUpDnShkgTimeRstcConfig_ValueChanged function.
private void button1_Click(object sender, EventArgs e)
{
ChartValuesChangedEventArgs chartValuesChangedEventArgs = new
ChartValuesChangedEventArgs(numUpDnShkgTimeRstcConfig.Value,
txtBxSmplWt1Form1.Text);
OnValuesChanged(chartValuesChangedEventArgs);
}
protected virtual void OnValuesChanged(ChartValuesChangedEventArgs e)
{
EventHandler<ChartValuesChangedEventArgs> handler = ValuesChanged;
if (handler != null)
{
handler(this, e);
}
}
Step 4 - Handle the event. This is where you update your chart with the new/updated values from Form2
private void ShowForm2Button_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.ValuesChanged += form2_ValuesChanged;
form2.Show();
}
void form2_ValuesChanged(object sender, ChartValuesChangedEventArgs e)
{
// Update the chart values here
Debug.Print(e.Value1.ToString());
Debug.Print(e.Value2);
}

How to access another class's method?

I have a WinForms application. In the main form, I coded a method that will clear all TextBoxes in whatever form is passed as a parameter. I want to call this method from another form. The following code is what I came up with after much trial/error and browsing this site. Is instantiating a new version of the main form every time the new form's clear all button is clicked good practice? If I were to make yet another form with it's own clear all button I would have to instantiate a new main form by similar practice (unless I made the method static)? Can anyone suggest alternative ways of accessing one form's method from a different form? Many thanks in advance.
Edit: I know making the method static would be a simple and effective solution, but I'm curious about using a non-static way.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void ClearAll(Form formToClear) //CLEAR TEXTBOXES
{
foreach (var box in formToClear.Controls.OfType<TextBox>())
{
box.Text = "";
}
}
}
public partial class NewItemForm : Form
{
public NewItemForm()
{
InitializeComponent();
}
private void clearAllButton_Click(object sender, EventArgs e)
{
Form1 mainForm=new Form1();
mainForm.ClearAll(this);
}
}
You don't have to make your ClearAll method static. It is enough if you keep a global reference to your main form. You can do it in Program.cs. This is not the best way though.
static class Program {
public static Form1 TheForm;
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
TheForm = new Form1();
Application.Run(TheForm);
}
}
Again! Just because it can be done, it does not mean that I would encourage you doing it. This is not in the spirit of OOP.
If the only reason you would like to access a Form1's method is to clear TextBoxes, then I would recommend creating an intermediate class:
public class InterForm : Form
{
public void ClearAll() //CLEAR TEXTBOXES
{
foreach (var box in this.Controls.OfType<TextBox>())
{
box.Text = "";
}
}
}
All other form should inherit from InterForm.
You should almost certainly create a static utility class with static functions. That will preserve memory by preventing unnecessary Form1 instances from being created. Depending on the size of your Form class and the objects/variables contained within, creating a new instance just to use 1 function from that class, could eventually result in a large amount of memory being lost over time. A static method in a static class would prevent that from happening because static methods are only defined/instantiated once in the lifetime of the process, versus once-per-instance.
You should probably go with something like:
internal static class FormUtils
{
internal static void ClearAllTextBoxes(Form form)
{
if (form == null)
return;
if (form.Controls.Count <= 0)
return;
foreach (var box in form.Controls.OfType<TextBox>())
{
box.Clear();
}
}
}
Then, that function would be used like this:
public partial class NewItemForm : Form
{
public NewItemForm()
{
InitializeComponent();
}
private void clearAllButton_Click(object sender, EventArgs e)
{
FormUtils.ClearAllTextBoxes(this);
}
}
You can use concept of Event here.
Your Another form form where you want to call method of your main form should be having a Event,
while creating an instance of this form (I guess you are creating an instance of this form from main form only) you can subscribe an event of this form to your targeted method.
So whenever you are required to call that method of your main form (from your another form), you can raise that event.
see below sample code.
Suppose Form1 is your main form
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
void f2_ClearTextBoxOfForm(Form targetForm)
{
foreach (Control control in targetForm.Controls)
{
if (control is TextBox)
((TextBox)control).Text = string.Empty;
}
}
private void btnShowForm2_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.ClearTextBoxOfForm += f2_ClearTextBoxOfForm;
f2.Show();
}
}
and Form2 is your another form from which you want to clear all textboxes of Form1
public delegate void ClearTextBoxEventHandler (Form targetForm);
public partial class Form2 : Form
{
public event ClearTextBoxEventHandler ClearTextBoxOfForm;
public Form2()
{
InitializeComponent();
}
private void btnClearTextBox_Click(object sender, EventArgs e)
{
if (ClearTextBoxOfForm != null)
{
//here passing 'this' means we want to clear textBoxes of this form (Form2)
//you can pass any Form's object of which you want to clear Textboxes
ClearTextBoxOfForm(this);
}
}
}

How to call Parent Form method from Child Form in C#?

I have a parent form with 1 method to refresh the panel content called resetPanel() .
I also have a button in the parent form. If I click the button, a new form opens up. I will do some changes and click on save. The content gets saved in the database and the child form closes. Now the parent form will be displayed.
I want to call the resetPanel() method now, so that the panel shows the updated values.
How can I achieve this?
If your child form is a dialog one, you can just check the form's dialog result:
// Do not forget to release resources acquired:
// wrap IDisposable into using(..) {...}
using (Form myChildForm = new MyChildForm()) {
//TODO: If you want to pass something from the main form to child one: do it
// On any result save "Cancel" update the panel
if (myChildForm.ShowDialog() != DialogResult.Cancel)
resetPanel();
}
In case your child from is not a dialog you can pass this into child form as reference to main one:
Form myChildForm = new MyChildForm(this);
myChildForm.Show(); // <- Just show, not ShowDialog()
...
private MyMainForm m_MainForm;
public MyChildForm(MyMainForm form) {
m_MainForm = form;
}
private void save() {
//TODO: Save to database here
// Main form update
if (!Object.ReferenceEquals(null, m_MainForm))
m_MainForm.resetPanel(); // <- resetPanel should be public or internal method
}
private saveButton_Click(object sender, EventArgs e) {
save();
}
After you close your Form2, you can call the ResetPanel method:
Form2 f2 = new Form2();
f2.ShowDialog();
resetPanel(); // <-- this will be executed when you close the second form
for Eg ur Parent Form Name If form Form1 and child Form Name as Form2 goto ur Child form Designer page Change it Access Modifier as Public
and from what ever method you want Call
Form2 f2=new Form2();
f2.Show();
.//from here on you can write your concerned code
If your resetPanel method is doing a database call, you quite possibly can avoid it. Although this will not get any data that was being updated by another user in your application. Just modified code from another answer of mine for your needs. This is just a sample:
public class ParentForm : Form
{
Button openButton = new Button();
public ParentForm()
{
openButton.Click += openButton_Click;
}
void openButton_Click(object sender, EventArgs e)
{
ChildForm childForm = new ChildForm();
childForm.OKButtonClick += childForm_OKButtonClick;
childForm.ShowDialog();
}
void childForm_OKButtonClick(object sender, MyEventArgs e)
{
// Use properties from event args and set data in this form
}
}
public class ChildForm : Form
{
Button okButton = new Button();
TextBox name = new TextBox();
TextBox address = new TextBox();
public event EventHandler<MyEventArgs> OKButtonClick;
public ChildForm()
{
okButton.Click += okButton_Click;
}
void okButton_Click(object sender, EventArgs e)
{
try
{
bool saveSucceeded = false;
// Try saving data here
if (saveSucceeded)
{
if (OKButtonClick != null)
{
MyEventArgs myEventArgs = new MyEventArgs();
// Just get updated data from screen and send it to another form
myEventArgs.Name = name.Text;
myEventArgs.Address = address.Text;
OKButtonClick(sender, myEventArgs);
}
Close();
}
else
{
MessageBox.Show("Data could not be saved.");
}
}
catch (Exception ex)
{
// Perform proper exception handling
}
}
}
public class MyEventArgs : EventArgs
{
public string Name
{
get;
set;
}
public string Address
{
get;
set;
}
}
Try to set the Save button in your child Form to DialogResult.Ok and then make the Save button as the AcceptButton for child Form. And then test if the result if it the user press that Save Button. Programmatically it could look like this:
Form2 chidForm = new Form2();
childForm.btnSave.DialogResult = DialogResult.Ok
childForm.AcceptButton = childForm.btnSave
if (childForm.ShowDialog() == DialogResult.Ok)
{
resetPanel();
}
Now, I assume here that your Save button in Child Form is named btnSave.

C# - Using two forms, access a variable from the first form

I have been struggling with this for a week now and I don't see any other questions about it. I need to do something such as at Accessing Forms data from another form but I need to access a variable that is in the first form's code FROM the second form, and the click event happens during the second form.
Here is some of the first form's (mainForm's) code:
namespace Sudoku
{
public partial class mainForm : Form
{
public mainForm()
{
InitializeComponent();
}
difficultyForm difForm = new difficultyForm();
public string difficulty = "";
private void generateNewPuzzleMenuItem_Click(object sender, EventArgs e)
{
generateBegin();
}
private void generateBegin()
{
difForm.Show();
difForm.difficultyTextBox.Text = "";
difForm.difficultyTextBox.Focus();
And here is some of the second form's (difficultyForm's) code:
namespace Sudoku
{
public partial class difficultyForm : Form
{
string difficulty = "";
public difficultyForm()
{
InitializeComponent();
}
private void enterButton_Click(object sender, EventArgs e)
{
difficulty = difficultyTextBox.Text;
if (difficulty != "1" && difficulty != "2" && difficulty != "3" && difficulty != "4" && difficulty != "5")
MessageBox.Show("The difficulty must be an integer from 1 to 5.", "Difficulty Error", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
else
{
this.Hide();
}
Also I am a noob at C# so if you have any other tips that would be great, thanks.
Note: I am using a string for difficulty because of something further down in the code, so please don't tell me to use an integer, thanks.
To push information from your second form to your main form you should use an event. Create the event on the second form and fire it when your button is clicked:
public partial class difficultyForm : Form
{
string difficulty = "";
public difficultyForm()
{
InitializeComponent();
}
public event Action<string> DifficultySubmitted;
private void enterButton_Click(object sender, EventArgs e)
{
difficulty = difficultyTextBox.Text;
if (DifficultySubmitted != null)
DifficultySubmitted(difficulty);
//...
}
}
Then subscribe to that event on the main form:
private void generateBegin()
{
difForm.Show();
difForm.difficultyTextBox.Text = "";
difForm.difficultyTextBox.Focus();
difForm.DifficultySubmitted += newDifficulty => difficulty = newDifficulty;
}
If I understand your difficulty correctly, you might want to look at event handling.
Define a custom event args class (eg: DifficultyEventArgs or something). Define a delegate with one param as your event args
Declare an event with the delegate in the class..
Invoke the delegate in the setter method of the property which you'd like to observe.
In the other form, you can subscribe to this event, to monitor any changes made to it. This is just one way.
Also, you should better use an enum for DifficultyLevel, instead of a string.
you can pass the Form1 in a constructor param of DificultForm, and so access the controls of Form1
If what you're trying to do is simply getting the value of your second forms's TextBox at an specific circunstance, you can create a public method in the second form's code
public string GetTxtBoxValue()
{
return difficultyTextBox.Text;
}
and then call it from the first form.
But, if you want a better control upon it, I'd recommend using an event.

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;

Categories

Resources