I'm having a little problem here when I'm trying to pass a cell information from a GridView in Form2 back to the Form1.
The problem is, Form 1 is already open and I cant access because his protection level
Here goes my code.
private void tableDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
System.Data.DataRowView SelectedRowView;
Database1DataSet.TableRow SelectedRow;
SelectedRowView = (System.Data.DataRowView)tableBindingSource.Current;
SelectedRow = (Database1DataSet.TableRow)SelectedRowView.Row;
Form1.nome_clienteTextBox = SelectedRow.nome_cliente;
}
In the forms designer, mark the Modifiers property of your textbox as Public
Or, better yet, have a public property on your Form1's class that changes the textbox:
public string NomeCliente
{
get { return nome_clienteTextBox.Text; }
set { nome_clienteTextBox.Text = value; }
}
And call it like:
Form1.NomeCliente = SelectedRow.nome_cliente;
That's assuming Form1 is your variable name (the instance of the original Form). If Form1 is the class name, then you need to instantiate it (which you already did when you opened it) and have a reference to it somewhere on the form from where you want to change it. A possible way to do it would be:
In Form2:
private Form1 _myFirstForm;
public Form2(Form1 myForm)
{
_myFirstForm = myForm;
}
private void tableDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
System.Data.DataRowView SelectedRowView;
Database1DataSet.TableRow SelectedRow;
SelectedRowView = (System.Data.DataRowView)tableBindingSource.Current;
SelectedRow = (Database1DataSet.TableRow)SelectedRowView.Row;
_myFirstForm.NomeCliente = SelectedRow.nome_cliente;
}
In Form1 (in case you open a new Form2 from Form1):
public void OpenForm2()
{
// this will more likely leak memory if you don't handle the
// disposing of Form2 somewhere else, but that's beyond the
// scope of this answer
var myForm2 = new Form2(this);
myForm2.Show();
}
Related
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);
}
Ok, am going to try and ask this without sounding dumb. I have a user form that I create dynamic textboxes inside a panel. I want to reference these textboxes or the panel from another form to send the texbox data to excel. I need to know how I can reference these controls. Thank you in advance!!
Create public properties on the user control, one for each element you want to access.
public class MyControl : UserControl
{
public string Name
{
get { return textBoxName.Text; }
}
public string Address
{
get { return textBoxAddress.Text; }
}
...
Then use those from the parent control that hosts the user control.
string name = myControl1.Name;
string address = myControl.Address;
Assume you have Form1 that dynamically adds a TextBox to panel panel1 during the load event like this:
private void Form1_Load(object sender, EventArgs e)
{
panel1.Controls.Add(new TextBox());
}
And you have Form2 from which you want to access the data on panel1. On Form2 you can add a public field to store the reference to panel1, but you can call it whatever you want. In this case, I use sourcePanel:
public partial class Form2 : Form
{
public Panel sourcePanel;
public Form2()
{
InitializeComponent();
}
}
Then you can pass the panel1 reference to any new Form2 instance when the new instance is created, for example from a button click event on Form1:
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.sourcePanel = panel1;
f2.Show();
}
Then on Form2, you can access all the values in the TextBoxes with code like this:
private void Form2_Load(object sender, EventArgs e)
{
foreach (TextBox txt in sourcePanel.Controls.OfType<TextBox>())
{
System.Diagnostics.Debug.WriteLine(txt.Text);
}
}
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;
I have a form1 (that runs the program) and form2 (that is a form for user to input). Form2 has a function that clears the user input (textboxes, checkboxes, combo boxes, it clears them).
The function looks like this:
public void CleartheForm(Control groupofcontrols)
{
foreach (Control c in groupofcontrols.Controls)
{
if (c is TextBox)
{
((TextBox)c).Clear();
}
if (c.HasChildren)
{
CleartheForm(c);
}
if (c is CheckBox)
{
((CheckBox)c).Checked = false;
}
label3.Text = "";
comboBox1.SelectedIndex = -1;
comboBox2.SelectedIndex = -1;
}
}
This works on its own. On my main form, I need to call this function, it should look like this:
I make a instance of form2 call Inputform and then:
private void Addrecord_Click(object sender, EventArgs e)
{
Inputform.ShowDialog();
if(Inputform.Addedrecord == true)
{
Inputform.Addrecord();
Inputform.CleartheForm(WHAT DO I PUT IN HERE??);
}
}
So that once a record has been added, the input form clears itself and ready for another record to be added.
The question is as above, what do I put in there? How do I call the groupofcontrols that is in the Inputform.CleartheForm() that is located in form2 from form1?? I tried to make a public Control groupofcontrols on the top of form2 and then leave my form1 as Inputform.CleartheForm(Control groupofcontorls), but then it saids I don't have object reference. If I leave it blank it saids Inputform.CleartheForm(); does not take 0 arguement.
Well, if you wanted to clear all the controls in the InputForm you could write another version of CleartheForm() without a parameter, and call the version with a parameter from it, like so:
public void CleartheForm()
{
ClearTheForm(this); // Passes all the controls in the Form.
}
Or you can just call the original ClearTheForm(Control) passing a reference to the InputForm as an argument: InputForm.ClearTheForm(InputForm).
If you always want to clear all the controls, I'd write a separate parameterless method for clarity.
However, this is only useful if you want to clear all the controls in InputForm.
Because Form is inherited from Control, you can call your method with form as an argument - it will clear all the TextBoxes and CheckBoxes in it:
Inputform.CleartheForm(Inputform);
However, probably, you can simply create new (and empty!) Inputform each time.
And, for your method - you should put
label3.Text = "";
comboBox1.SelectedIndex = -1;
comboBox2.SelectedIndex = -1;
away from the loop.
From what you've said (i.e. you put the groupofcontrols as public on form2), this should work:
Inputform.CleartheForm(Inputform.groupofcontrols);
(This is considering that Inputform is a property or a field on your main form - which I observed it is as you're calling ShowDialog on it.)
I don't understand your program's workflow.
If it is:
Form1 opens Form2
User input data into Form2
User press OK button on Form2
Form2 closes
Form1 reflect changes which was made by the user in Form2
User can repeat from the step 1
You should use new instance of the Form2 for the each iteration
To do that you should remove any clear code from your Form2 and change your code to the next one:
private void Addrecord_Click(object sender, EventArgs e)
{
var inputForm = new Form2();
inputForm.ShowDialog();
if(inputForm.Addedrecord == true)
{
...Reflect changes here...
}
}
But if you need a Form2 should stay opened while a Form1 adds new record each time when user click "Ok" button on the Form2
You should call Form1 from the Form2, the next design will be nice
interface IDataTarget
{
void Update(int id, string name); // you should reflect here all of your data
}
class Form1
: Form, IDataTarget
{
public void Update(int id, string name)
{
// add new record here
}
private void AddButton_Click(...)
{
using(var form2 = new Form2(this))
{
form.ShowDialog(this);
}
}
}
class Form2
: Form
{
private readobly IDataTarget dataTarget;
public Form2(IDatatarget dataTarget)
{
this.dataTarget = dataTarget;
}
private OK_Click(...)
{
dataTarget.Update(textBox1.Text, textBox2.Text);
ClearTheControls();
}
}
Personally I would move this method into a class library. You can make it static class and then just call
FromControls.CleartheForm(Inputform.groupOfControls)
So, your new class in a class library is (and nothing has been tested here, so mistakes are likely!)
public static class FormControls
{
public static void CleartheForm(Control groupofcontrols)
{
foreach (Control c in groupofcontrols.Controls)
{
if (c is TextBox)
((TextBox)c).Clear();
if (c.HasChildren)
CleartheForm(c);
if (c is CheckBox)
((CheckBox)c).Checked = false;
}
}
}
I would remove the following code:
label3.Text = "";
comboBox1.SelectedIndex = -1;
comboBox2.SelectedIndex = -1;
...as the CleartheForm code above will clear it.
So, your code would be (remembering to add a reference to your class library)
private void Addrecord_Click(object sender, EventArgs e)
{
AddRecord();
}
private void AddRecord()
{
Inputform.ShowDialog();
if(Inputform.Addedrecord)
{
Inputform.Addrecord();
FromControls.CleartheForm(GetControlOnPage())
}
}
private control GetControlOnPage()
{
//logic to return control if needed although it may just be this:
return Inputform.groupofcontrols
}
I have 2 Forms. Form1 creates Form2 like this:
public partial class Form1 : Form
{
private void button3_Click(object sender, EventArgs e)
{
Form2 AcqForm = new Form2();
AcqForm.Show();
string[] ret = AcqForm.fulldate;
MessageBox.Show(ret[27]);
}
}
public partial class Form2 : Form
{
public string[] fulldate; //Created in form 2
close(); //Need to get this string back on or before close event
}
How should I go about doing this?
You need to handle the Form2 instance's FormClosed event in the first form and access the public properties.
Using this snippet, you can get a little knowledge on it.
in Form1:
using(Form2 form2 = new Form2())
{
if(form2.ShowDialog() == DialogResult.OK)
{
MessagBox.Show(form2.fulldate);
}
}
In Form2:
public partial class Form2 : Form
{
public string[] fulldate {get; set;} // Create a Property
void CloseForm()
{
fulldate = "valueToReturn";
DialogResult = DialogResult.OK;
}
}
Assuming you want button3_Click to wait until AcqForm is closed before accessing fulldate, you'll first have to change AcqForm.Show(); to AcqForm. ShowDialog();. (Show() doesn't wait for it to close.)
As for the fulldate field – it will be accessible even after the form closes because the form still exist. SLaks' remark about it being a 'field' means that we have different names for different types of 'variables'. What you have declared in the class (without get and set) is called a field. A variable in a method is called a 'variable'.
If you still want to do something when AcqForm closes, do this:
In Form1's constructor, before the AcqForm. ShowDialog();:
AcqForm.FormClosing += AcqForm_FormClosing;
And in Form1's class:
void AcqForm_FormClosing(object sender, FormClosingEventArgs e)
{
//Whatever will be here will be done when the form is closing.
//Use 'FormClosed' for doing things AFTER the form has closed.
}