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;
Related
Let's say I have a Form called Form1 which will somehow (how is not relevant) calls another form Form2
(Form1)
Form2 f2= new Form2();
f2.ShowDialog();
This Form2 has a button that will do some operation everytime the user clicks on this button.
However, I want that the first time i.e. when Form2 is just shown, the code in the button (some operation) gets executed.
In other words I have to be able to call the code in Form2's button_Click which is private.
Now I can think of some ways to make this possible(making the click event public etc) , but my question is what is the most elegant (or correct) way to do this?
I would add a property to Form2 to tell the form I like to automatically executed an action.
class Form2
{
public bool AutoExecuteSomeOperation { get; set; }
}
In Form1, you would set that property and in Form2 you would check and execute appropriate code if the property was set.
I would recommend that you refactor button_Click to call another method which you can also call for automatic execution. I like to keep event handler simple and executed only for the event on the control that served to name the event handler. Thus, you know that button_Click is an handler for a Click event on a control named button. It makes the code easier to maintain.
You can decide if you want to reset the property once the code is executed or you can add some validation that the property changes are valid. For exemple, you might want to ensure that the property is called before displaying the form.
In all cases, you should avoid having any reference to a control from an external form. Only Form1 itself should know that it contains a button. Any use from outside world should be done through a public property or public event of the form. That way, if you decide that the button should be replaced by an hyperlink, a menu item, a checkbox or anything else Form1 does not need to be updated. This is very similar to what should be done for UserControl. The less internal details leak, the easier it will be to make internal changes without having to update all caller.
The easiest approach is just make it public, however its not the bastion of great design.
Decoupled messaging is probably where you want to be, event aggregator or any pub sub method messaging system. This is a more modern and scalable approach, the participants need not know about each other allowing you to make the methods private and giving you a more maintainable decoupled solution, and keep your classes self consistent.
Unity, MvvmLight both have these sorts of messaging systems, however there are lots of them.
Example of how this might work
public Form1()
{
InitializeComponent();
EventPublisher.Instance.Subscribe<NewUserCreated>
(n => listBoxUsers.Items.Add(n.User.Name));
}
...
// some other class
private void Form2()
{
var user = new User()
{
Name = textBoxUserName.Text,
Password = textBoxPassword.Text,
Email = textBoxEmail.Text
};
EventPublisher.Instance.Publish(new NewUserRequested(user));
}
Move the code from the OnClick event into its own method (e.g. "DoWork"), then call that method from the OnClick event.
Either call it when you create the form
var frm = new demoForm();
frm.DoWork();
frm.Show();
Or call it in the forms constructor.
public partial class demoForm : Form {
public demoForm() {
InitializeComponent();
DoWork();
}
private void button1_Click(object sender, EventArgs e) {
DoWork();
}
public void DoWork() {
//Code here
}
}
I know how to pass data using event and delegate from Form2 to Form1 (backwards actually).
But I would like to know how to do it appropriately from Form1 (main form) to Form2.
Imagine Form2 and some center form to show some progress (with a progressbar) which would be common for plenty of other forms.
This is how I would like to look like:
public partial class Form2 : Form
{
public delegate void ProgressEvent(object obj);
public event ProgressEvent OnProgressShowing;
public Form2()
{
}
private void ShowingProgress(object obj)
{
//calling this method from Form1
//But it must be PRIVATE!
}
}
How to do it?
Like?
Form2 f2 = new Form2();
f2.OnProgressShowing += new Forms.ProgressEvent(?? ?what to put inside here?? I cannot access a private method on form2 ???);
I know one option is to create delegate and event on Form1, and pass a Form1`s reference to Form2, and subscribe to an event from Form2. But this is not what I would like. I would then have plenty of delegates and events in each of the other forms which would call this form2.
Since your first form is creating an instance of your second form and "owning" that instance, it is appropriate design for the method on Form2 that updates the UI based on the current progress to be public, and for the other forms calling it to call that method. There is also no need for Form2 to have an event at all, since it is not the one informing other forms that something has happened.
In this case, when creating a design document to indicate the relationships between these forms, we can say that Form1, or other forms have a Form2. A HAS-A relationship makes sense here. For Form2 it's goal is simply to display progress based on information provided by another class, so having a public method for another class to tell it to display progress is correct.
You're missing up a reversed relationship. If the child form needed to inform the parent forms of something, then Form2 would have an event, and in the handler of that event the forms creating it (i.e. Form1) would generally be calling their own private methods in the handler, or possibly accessing other public methods of Form2 to pull or push data out of it.
The idea here is that is'a appropriate for Form1 to "know about" Form2. It's appropriate for it to have a reference to it, and to know about whatever it exposes publicly. Form2, however, shouldn't know anything about what form creates it. It should be able to display progress for any form that can tell it what progress to show. If it needs to accept a reference to Form1 or know anything about it at all, then that can't happen. By using an event on Form2 when it needs to pass information out to the form that creates it, it can avoid needing to know what form that is.
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);
I have 2 forms in C# desktop application. Form1 and Form2.
Form1 contains a public method that adds item in ListBox control as follows:
public void AddToList(string item)
{
listBox.Items.Add(item);
}
When I call this method directly on some button press then it works fine. But when I call this method from Form2, it doesn't add anything in ListBox control on Form1. Code in Form2 is as below:
Form1 frm = new Form1();
frm.AddToList("something");
When I run this nothing happens. No error nothing. It just doesn't add any item into ListBox.
What am I doing wrong?
You're creating a new instance of Form1 and adding an item to it's listbox, rather than getting an instance of the Form1 you no doubt already have and calling the method on that.
The naive approach is to have a parameter in the Form2 constructor that takes an instance of Form1 and saves it as an instance variable for use in this event handler.
I don't much like that approach from a design perspective.
I would suggest creating a public event in Form2, having Form1 subscribe to that event and add a handler that add the item to the listbox. The Event in Form2 would look something like this:
public event EventHandler ButtonClick
{
add
{
button1.Click += value;
}
remove
{
button1.Click += value;
}
}
Then you'll have a property that looks something like this:
public string SomeValueForm1NeedsOnButtonClick
{
get
{
return texbox1.Text;
}
}
Then in Form1 you'll have something like:
Form2 otherForm = new Form2();
otherForm.ButtonClick += (sender, args) =>
{
listbox1.Items.Add(otherForm.SomeValueForm1NeedsOnButtonClick);
};
This approach ensures that each form only knows as little as possible about each other form. It reduces Coupling between the two classes and makes it clearer to future users/readers of the forms exactly what communication takes place between them.
Form1 frm = new Form1();
this line is creating a brand new instance of Form2... not the same instance that is already displayed on the screen. so you are adding to the listbox of this secondary instance that is never shown on the screen.
Hmm
If you followed that code with frm.Show() you would have seen it. Isuspect that's not waht you want.
Your approach to the is problem is a tad naive.
You could add a property to form2 and set it to the Form1 instnace you want to use. (PS form1 and form2 are not helping, give them propernames. MainForm and DetailForm or somesuch).
The problem with the above is you've implemented a horrible dependancy.
Lots of ways to go with this, one would be a seperate class to hold the list (an interface and a class would be even better).
Then add a property to Form1 and Form2 of teh ihneterface or class type.
Form2 can then add things to the list.
That raises a list changed event.
Form1 hooks into with an event handler and then refreshes the listbox it's using to display the the doings.
Once you have the infrasturure in polace you can do all sorts of things with it, whereas the method you are using is a lot of code and messing about for very little reward.
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.
}