It can happen when developing an application to need multiple forms.
We will take the example of an agenda, on the main form (frmMain), we have a grid that represents slots spread over a week. The second form (frmRDV) will present the details of an appointment.
We will not dwell on all the controls of these two forms for this tutorial, just think that frmRDV will open when you click on a time slot.
THE SHOW METHOD
The “basic” way to display frmRDV is to create an instance of this form and display it with the Show method.
C# Code:
1 2 3 4 5 6 7 |
private void crenauHoraire_Click(object sender, EventArgs e) { frmRDV frm = new frmRDV(); frm.Show(); } |
But there is no interaction, each form lives its life independently. How to know in frmRDV what is the start time of the slots, the end time, if there is already an appointment etc … And even once the details created, modified or deleted how frmMain will know if the slot should to be posted busy or not?
THE SHOWDIALOG METHOD
This method makes frmRDV modal, ie the user will have to close this form to access frmMain again.
C# Code:
1 2 3 4 5 6 7 |
private void crenauHoraire_Click(object sender, EventArgs e) { frmRDV frm = new frmRDV(); frm.ShowDialog(this); } |
There is a beginning of interaction, because frmMain is blocked while frmRDV is displayed, but still no data transfer.
INPUTBOX
The InputBox control as it exists in VB6 (for example) does not appear in the .Net controls arsenal. However, it is neither more nor less than a modal form that returns information to another.
Suppose we want to retrieve a string, let’s add a public method of type string to frmRDV, this method will display the form in modal mode and return the content of a textbox once it is closed.
C # code:
1 2 3 4 5 6 7 |
public string InputBox () { this.ShowDialog (); // display the form in modal mode, the execution of the code of this method is blocked on this line as long as the form is displayed return lTextBox.Text; // return the contents of the TextBox once the form is closed } |
We finally have a data transfer, but in one way, of a single type and only at the closing of frmRDV.
With an DetailRDV class, we can return to frmMain all the information needed to register an appointment. However, it is not possible to transfer information in the other direction.
BIDIRECTIONAL INPUTBOX
Since we have converted frmRDV to InputBox using a dedicated method, passing parameters to this method is a way to transfer data from frmMain to frmRDV.
C # Code:
1 2 3 4 5 6 7 8 9 10 |
private DetailRDV rdvEnCourse; public DetailRDV InputBox (DetailRDV RdvDisplay) { rdvCurrent = RdvDisplay; // Write here the code for the display and possibly the treatment of the appointment to display this.ShowDialog (); return rdvEnCours; // return the current appointment, in the state where it is when closing the form } |
So finally we have an exchange between the two forms, remain two disadvantages:
– The opening of one blocks the execution of the other;
– The return information transfer can only be done at the closing of the second form.
PASSING PARAMETERS IN THE FORM BUILDER AND GENERATING EVENTS
If our frmRDV form has a parameter constructor and can generate public events at different stages of the input (eg an event when the start time is selected or changed, the same as the end time and one for the final validation of the other details), then we will be able to pass our parameters to frmRDV at the instantiation of it and subscribe frmMain to the various existing events.
Bidou wrote a source in C # which is a perfect example of this principle.
For the reader who would code in VB, there are translators in free lines (keywords: “convert C # VB.Net” in his favorite search engine). But with a little intellectual gymnastics it’s, I think, within everyone’s reach to understand the code.
BINDING AND PROPERTYCHANGED
I have already discussed notions of Binding here. In the same form it works alone.
Between two forms, the class used must implement INotifyPropertyChanged.
C # code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
using System; using System.ComponentModel; namespace test { public class DetailRDV: INotifyPropertyChanged { private DateTime start; private DateTime end; private title string; public DateTime Debut { get {return debut; } set { start = value; GenerereLaNotification ( "Start"); } } public DateTime End { get {return end; } set { fin = value; GenerereLaNotification ( "End"); } } public string Title { get {return title; } set { title = value; GenerereLaNotification ( "Title"); } } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; private void GenerateLaNotification (string NameProp) { if (PropertyChanged! = null) PropertyChanged (this, new PropertyChangedEventArgs (PlotName)); } #endregion } } |