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;
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);
}
}
In my project I have a Settings form and a Main form.
I'm trying to call the Main form's MasterReset function from the Setting form, but nothing happens.
The Master form's Masterreset function looks like this.
public void MasterReset()
{
DialogResult dialogResult = MessageBox.Show("Are you sure you want to perform master reset? All settings will be set to default.", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dialogResult == DialogResult.Yes)
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string phonebook_path = path + "\\Phonebook\\Contacts.xml";
XmlDocument xDoc = new XmlDocument();
xDoc.Load(phonebook_path);
XmlNode xNode = xDoc.SelectSingleNode("People");
xNode.InnerXml = "";
xDoc.Save(phonebook_path);
listView1.Clear();
people.Clear();
}
else if (dialogResult == DialogResult.No)
{
return;
}
}
And I'm accessing it from the Settings form like this
private void btn_MasterReset_Click(object sender, EventArgs e)
{
Main f1 = new Main();
f1.MasterReset();
}
Why am I not seeing any results?
Do you know what composition over inheritance is?
In the form where you have MasterReset you should do something like this:
Llet's suppose that in your second form you have something like this, and let's suppose your "mainform" will be called "MasterForm".
public partial class Form1 : Form
{
private MasterForm _masterForm;
public Form1(MasterForm masterForm )
{
InitializeComponent();
_masterForm = masterForm;
}
}
Here's the code in your masterForm Class:
private void button2_Click(object sender, EventArgs e)
{
Form1 form1 = new Form1(this);
}
Here's in your form1:
private void btn_MasterReset_Click(object sender, EventArgs e)
{
_masterForm.MasterReset();
}
Hope this helps!
This worked for me: In your Program class, declare a static instance of Main (The class, that is) called Form. Then, at the beginning of the Main method, use Form = new Main(); So now, when starting your app, use
Application.Run(Form);
public static Main Form;
static void Main() {
Form = new Main();
Application.Run(Form)
}
Now, calling a function from another form is simple.
Program.Form.MasterReset(); //Make sure MasterReset is a public void
namespace F1
{
// Method defined in this class
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//This method I would like to call in other form
public void function()
{
MessageBox.Show("Invoked");
}
// opening the new form using button click
private void OpenNewForm_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.ShowDialog();
}
}
// This is second form
public partial class Form2: Form
{
public Form2()
{
InitializeComponent();
}
// on button click Form1 method will be called
private void button1_Click(object sender, EventArgs e)
{
var mainForm = Application.OpenForms.OfType<Form1>().Single();
mainForm.function();
}
}
}
There are multiple solutions possible. But the problem itself arise from the bad design. If you need something to be accessed by many, then why should it belong to someone? If, however, you want to inform something about anything, then use events.
Your mistake is what you are creating another instance of form1, thus MasterReset is operating with form, which is not even shown.
What you can do:
Make (as Ravshanjon suggest) a separate class to handle that MasterReset (and maybe something else). But also add to it an event. form1 and form2 can both subscribe to it and whenever either of them call MasterReset - both will react.
Create form dependency (as BRAHIM Kamel suggested): when you create form2, then pass to it form1 instance (as constructor parameter or by setting public property), to be able to call public non-static methods of form1.
As a quick, but relatively legimate solution, make this method static:
private static Form1 _instance;
public Form1()
{
InitializeComponents();
_instance = this;
}
public static void MasterReset()
{
// alot of code
_instance.listView1.Clear();
// alot of code
}
this way you can call MasterReset from any other form like this Form1.MasterReset(). Disadvantage of this method is what you can not have more than one instance of form2 (which is more likely anyway).
I understand your problem, you can declare your function as public static void(also listView1 and people should be static too). Then when you want to call to like this:
private void btn_MasterReset_Click(object sender, EventArgs e)
{
Main.MasterReset();
}
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());
}
}
I've stomped with a problem I've spent some hours trying to solve, with my very limited knowledge.
I have a listview in my form1 called listMachine
And I have a method in form1.cs such as
private void máquinaToolStripMenuItem_Click(object sender, EventArgs e)
{
machinename open = new machinename();
open.Show();
}
machinename.cs is another form, and I use that method to open my other form, with an object called open.
the machinename button is a simple form which just serves as an input receiver, it asks a name, we have to type it into the textbox, press a button and it receives the input.
This is the code that runs when you press the button
public void buttonAceitarnome_Click(object sender, EventArgs e)
{
if (textBoxnomenova.TextLength == 0)
{
toolTipEmptyname.Show("O nome da máquina não pode estar vazio", textBoxnomenova);
}
else
{
Variables.var = textBoxnomenova.Text;
//MessageBox.Show(Variables.var); debug purpose, the messagebox does carry variables.var text
obj.listMachine.Items.Add(Variables.var); //If I change the variables.var to "test" it will NOT add the item.
this.Close();
}
}
Also, I forgot to mention my Variables.cs class, I created it because it was the only way I found to pass variables from a class to another (machinename.cs to form1.cs), but still, the items are not added into the listview.
This is my variables.cs code
public static class Variables
{
public static string var;
}
The comments I added to the code also give you some extra debug info..
I didn't want to ask for online help, but couldn't solve this on my own :(
If I were you, I would first remove the Variables class.
Then, you'r first form/class is called obj.cs, am I right? Or is it form1.cs?
I made it look like this:
public partial class obj : Form
{
public static string text; //This is a variable that can be reached from
public obj()
{
InitializeComponent();
}
private void máquinaToolStripMenuItem_Click(object sender, EventArgs e)
{
machinename open = new machinename();
open.ShowDialog(); //I put ShowDialog instead of Show
addItem(); //This method is called when the showed dialog is closed (machinename.cs)
}
private void addItem()
{
listMachine.Items.Add(text);
}
}
and the machinename.cs class like this:
public partial class machinename : Form
{
public machinename()
{
InitializeComponent();
}
private void buttonAceitarnome_Click(object sender, EventArgs e) //This one can be private
{
if (textBoxnomenova.TextLength == 0)
{
//Something here
}
else
{
obj.text = textBoxnomenova.Text; //Initializing the public static variable
this.Close(); //Closes the form, next step will be to run the method in obj.cs
}
}
}
If I understood your question correctly, you wanted to add an item to the ListView called "listMachine" via a button in the form "machinename.cs". This code will do that. I hope it helps you.
Change the click event from private to protected.
protected void máquinaToolStripMenuItem_Click(object sender, EventArgs e)