Παιδιά, νομίζω ότι το παρακάνατε. Καταρχήν, το θέμα το έχουμε ξανασυζητήσει δεκάδες φορές. Μία απλή αναζήτηση θα σας είχε δώσει αμέσως την απάντηση. Κατά κανόνα κάποιος έρχεται και ρωτάει πως θα πειράξει τα controls μίας φόρμας από μία άλλη φόρμα. Η απάντηση πάντα είναι ότι αυτό είναι κακή ιδέα και καλύτερα να φτιάξει μεθόδους τις οποίες θα καλεί από την άλλη φόρμα.
Ακριβώς επειδή το θέμα έχει εξαντληθεί δεν συμμετείχε και κανένας από τους moderators ως τώρα στη συζήτηση. Διαπίστωσα όμως ότι τελικά η συζήτηση ξέφυγε και αρχίσαν να γίνονται επικίνδυνες προτάσεις, για ένα απλούστατο θέμα.
Η λύση είναι επίσης απλή. Δεν υπάρχει κανένας απολύτως λόγος να χρησιμοποιήσει κανείς static μεθόδους ή πεδία, Close μέσα σε κουμπιά, κουμπιά μέσα σε Close, επιπέον κλάσεις, MDI φόρμες, παραπομπή σε WPF αντί για Winforms ή οτιδήποτε παραπέμπει σε rockect science.
Μία φόρμα είναι απλά μία κλάση. Όταν εμφανίζεται μία φόρμα στο χρήστη απλά δημιουργείται ένα instance της κλάσης και εκτελείται ο κώδικας που θα ζωγραφίσει το UI στην οθόνη. Όπως με κάθε κλάση, αν θέλουμε να περάσουμε κάποιο reference σε άλλη κλάση είτε χρησιμοποιούμε κάποιο property στο οποίο θα θέσουμε το reference, είτε καλούμε κάποιο method στο οποίο περνάμε το reference ως παράμετρο. Επειδή τώρα η FormA και η FormB δεν ξέρουν η μία την άλλη, την ανταλλαγή references θα πρέπει να αναλάβει η main form, η φόρμα η οποία δημιουργεί τις άλλες.
Από τη στιγμή που η μία φόρμα (FormA) έχει reference στην άλλη (FormB) μπορεί να καλέσει οποιαδήποτε public method της άλλης φόρμας. Μεταξύ αυτών και την Form.Close.
Ακόμα καλύτερα βέβαια είναι να μήν ξέρει η μία φόρμα για την άλλη αλλά να επικοινωνούν μεταξύ τους μόνο μέσω της κυρίως φόρμας. H FormA σηκώνει ένα event το οποίο ακούει η MainForm και καλεί την FormB.Close
Μία απλούστατη υλοποίηση είναι παρακάτω. Όπως βλέπετε οι δύο φόρμες δεν κάνουν ουσιαστικά τίποτε. Μόνο η FormA σηκώνει το CloseOtherForm event. Αλλά και η MainForm πάλι δεν κάνει κάτι ιδιαίτερο. Απλά καλεί την Close της FormB:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
FormA formA = new FormA();
FormB formB = new FormB();
private void MainForm_Load(object sender, EventArgs e)
{
formA.CloseOtherForm += new EventHandler(formA_CloseOtherForm);
formA.Show();
formB.Show();
}
void formA_CloseOtherForm(object sender, EventArgs e)
{
formB.Close();
}
}
public partial class FormA : Form
{
public event EventHandler CloseOtherForm;
public FormA()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
CloseOtherForm(this,new EventArgs());
}
}
public partial class FormB : Form
{
public FormB()
{
InitializeComponent();
}
}
}
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos