Accessors (Properties) without Form.ShowDialog() - c#

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);
}

Related

trouble with passing information from a form to another

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();
}

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();
}

Send parametny from one form to another in 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);
}
}

Categories

Resources