I have two Forms
Parent Form : properties : Total Value. Button to load child form.
Child Form: property : insert Value.
When I run application, Parent form loaded first. I can load second (Child) form by click button.
Problem is that when I insert value in child form parent form is not showing any changes even I pass value by delegate and other methods.
I don't want to reload Parent Window. Please help
What you should be doing is creating events on the child for (or using the existing events if they will do the job) and having the parent form subscribe to those events.
One common example is to have the parent hide itself, show the child, and then show itself again when the child is closed. Here is some code that does that:
//in parent form
private void someButtonClickHander(object sender, EventArgs args)
{
ChildForm child = new ChildForm();
this.Hide();
child.Closing += (sender2, args2) =>
{
var someResultFromChildForm = child.SomePropertyOnChildForm;
this.Show();
}
child.Show();
}
If the closing event doesn't work for you (maybe you want to do something when the child form presses a button) you may need to have the child create it's own event. There are lots of tutorials on MSDN or other sites on how to do this. If you have trouble with that (or any other aspect of this design) please ask for clarifications in comments.
If you want to keep data consistent between multiple forms, I recommend putting the data into an object that you can reach from both forms.
The most direct way is to implement INotifyPropertyChanged for the object, so you can bind to this object in both forms and any changes made will trigger the property change event.
For more complex scenarios I make an object that has custom events that I can subscribe to, as INotifyPropertyChanged can be lack the subtlety needed in complex scenarios. As an example, I have a "Helm" object for my primary navigation form that all of the UI elements subscribe to. If a navigation event occurs, the helm does all of the navigation and data loading, and then it triggers a series of events that the UI listens to.
For a simple parent child this can seem like overkill, but this model (having one truth for the current state that the UI simply subscribes to) allows your UI to evolve and for each element of the UI to only worry about its own needs.
Have a Property called Parent in your child form. When you create the instance of the Child,Pass the current object( parent form object) to the constructor where you will set it as the Parent property value of child. In Parent form Have a Public Method in your Parent form. P
parent form
Form1 : Form
{
decimal _totalPrice;
public void UpdateTotal(decimal val)
{
_totalPrice=_totalPrice+val;
lblTotal.Text=_totalPrice.ToString();
}
}
Child Form
Form2:Form
{
public Form1 Parent { set;get;}
public Form2(Parent parent)
{
this.Parent =parent;
}
}
When creating the object of Child form
Form2 objChjild=new Child(this);
//do whatever
Now from child form, if you want to update the total,
call like this
this.Parent.UpdateTotal(200);
Related
I am new to .Net Winforms, i generally work on either console apps or MVC.
I am developing a MDI WinForms application, and if I make a change in one (any) window, I need all other open MDI forms to refresh when the change has been made so they can also show the updated data.
How can this be achieved - In my old Delphi (v3) days, you used to "publish" a WM_USER type message and each form would have a "subscriber handler" that would then take the required action but that was a long time ago.
All the forms are slight variations of the data and a change in one form can affect the data in the others..
TYIA
You need an event system between children and parent, which can be accomplished as follows:
Create a base class for your child forms that contains an event to be raised when any data on the form is changed. Let's call it FormChanged event.
Add an event to the Parent form to notify all children. Let's call it ChildFormChanged event.
Upon instantiation of each child form, have the parent form subscribe to the FormChanged event of the child, AND have the new child form subscribe to the ChildFormChanged event of the parent form.
The event handler for the FormChanged event in the parent form is just a pass-through function, that in turn raises the ChildFormChanged event, passing the information received from the child form causing the event to fire.
The ChildFormChanged event can be handled in the base class for child forms via a virtual event handler (to handle generic items) that can be overridden in each child class (to handle specifics of each child form).
I wrote and commented an example app in C# and posted it on Github. Here's the relevant code:
Base child Form:
public event EventHandler<EventArgs> FormChanged;
public virtual void ProcessChange(object sender, EventArgs e)
{
if((sender as Form) != this)
{
//Handle change
}
}
protected void NotifyParent() => FormChanged?.Invoke(this, EventArgs.Empty);
Parent form:
public event EventHandler ChildFormChanged;
public void NotifyAllChildren(object sender, EventArgs e)
=> ChildFormChanged?.Invoke(sender, e);
//Child form creation function
private void createNewFormToolStripMenuItem_Click(object sender, EventArgs e)
{
MDIChildBase newChild = new MDIChild(); //Can be different child forms
newChild.MdiParent = this;
//Parent-child event subscription
newChild.FormChanged += NotifyAllChildren;
ChildFormChanged += newChild.ProcessChange;
newChild.Show();
}
Every child form must call base.NotifyParent(); once any changes occur that you want to propagate to other child forms.
You can still use the windows messaging infrastructure. Explained here and here.
I have two forms. One is a parent form with a button and a child form with a radio button. i want to enable/disable Button in parent Form Based on if the Radio Button in Child Form is Enabled. Should i raise an event or there is an alternative way to achieve this.??
Events are a nice and robust way to handle this.
They will take a bit more code, but it could be worth it if you want a robust solution that you can extend in the future, etc.
On the other hand, if you just want to quickly solve your problem, there are two more commmon solutions.
when you create the child form, you can pass it a reference to the parrent form that created it (through the constructor)
something like
public partial class Form2 : Form
{
private Form1 parrentForm;
public Form2(Form1 parrent)
{
parrentForm = parrent;
}
When you create the child form, you pass it the reference
//from inside Form1
Form2 frm2 = new Form2(this);
You might declare a public method inside Form1
public void EnableButton() {
}
then call it from form2 with the reference you stored
parrentForm.EnableButton();
you can even make the button in Form1 public (from the gui, select the button, in the properties pane change the "Accessibility" property to "Public" instead of "Private" which is default.
Then in form2 you could do
parrentForm.Button1.Enabled = false;
these are all quick and somewhat dirty solutions.
Events are more clear for complex uses.
In the end, go with what makes the most sense.
I like the answer above but just to mention, you could use an event as well.
public event EventArg RadioButtonHasChanged;
I have a MDI Form with 2 mdi children forms. On both the children forms I have a shared usercontrol (data grid) and the way the usercontrol has to work is exactly the same except for a filter on the one form.
All works well, however, I do have a problem with Events. I created a couple of eventhandlers to detect when things like save/search/load etc happens on the data. However, I don't want both child forms to for example to fire the search event. If I search data on ChildForm1, I dont want ChildForm2 to fire the search event as well.
I tried using Visible and IsAccessible to detect if the usercontrol is on the front of the Mdi forms, but that does not work.
Another option is to see if the parent is the active Mdi form, however, I sometimes have a couple of panels as the parent etc. Which makes it a difficult solution for future development or other scenarios.
Any suggestions?
edit: what I am currently doing is:
private void TransactionLoad_Event(object sender, EventArgs e)
{
if (loading) return;
Form parentForm = this.FindForm();
Form mdiParentForm = (Form)this.TopLevelControl;
if (mdiParentForm != null && parentForm != null && mdiParentForm.ActiveMdiChild == parentForm)
LoadTransactions();
}
Thanks Eugene.
I am creating a multiple form windows application using C#, I have two form one Parent form and a child form.
From parent form I called the child form to add a tree node in the parent form treeview. After entering the details in the child form and pressing "Add" button I want to close the child form and want to add the tree node in the treeview dynamically inside the parent form.
The value is passing perfect, I am using properties for the transfer. Rest by using this.Show() another parent form opens up. I have already tried Invalidate() and Refresh() but the treeview does not get updated.
Override child form constructor to accept parent form as parameter
ChiildForm chilForm=new ChildForm(parentFormObject);
Now you can call method of parent form that would make the required change on the page.
parentFormObject.RefreshSection();
but the treeview does not get updated
To refresh the treeview you need to rebind it to your datasource after adding the newly added item of child form.
Example:
List<SomeClass> items = new List<SomeClass>();
if(childForm.ShowDialog() == DialogResult.Ok)
{
items.Add(childForm.newlyAddedItem); //you have mentioned that values are passing perfect
//your code for rebinding to the treeview
}
If you want to refresh after clicking Add buttons,
just try to call the load_ function by sending the parameters.
example,
button_click(Object sender,Event_args e)
{
Form_Load(sender,e);
}
I have a simple problem: I have a main form in win-forms/c#. It has a listbox bound to a database.
When I click a button a new form is created.
When I click a button on the child form, I want to call a method that exists in the main form, that updates the list box or alternatively when the child form closes, to call that function.
Is this possible??
There are many ways to achieve this, but here's a simple way. In your main form, when you create and show a child form, do it like this:
ChildForm child = new ChildForm();
child.Show(this); // this calls the override that takes Owner parameter
Then, when you need to call a method in the main form from the child form, use code like this (assumes your main form is of type MainForm):
MainForm parent = (MainForm)this.Owner;
parent.CallCustomMethod();
A more complex way would be to use a form of dependency injection, where you would pass in a reference to the parent form (or more properly, to its interface) in the constructor of the child form. But the above way is simple and probably effective enough for your purposes (and it actually is a form of dependency injection itself, sort of).
Scenario 1: Call a method in Parent Form on click of button in child form.
Create an Event in Child Form. Raise that event on some Button Click etc. Subscribe to that event in your Parent Form and call the parent's form method inside that.
Scenario 2: Call a method in Parent Form when Child Form is closed.
Handle the FormClosed or FormClosing event of Child Form in the Parent form and call the parent's form method inside that.
ChildForm frm = new ChildForm();
frm.FormClosed += new FormClosedEventHandler(frm_FormClosed);
void frm_FormClosed(object sender, FormClosedEventArgs e)
{
//Call your method here.
}