I build a Windows Form Application with a single form. I want to write it into such a program: the operation of any instance of the form will be reflected on all other instances. what should I do?
This is an interesting question. I guarantee that some clever programming has recommended me to use delegates. Before this happened, let us first explore several solutions to this issue.
Assume that I have two forms, each form has two TextBox controls: TXT1STDATA and TXT2NDDATA. How can I keep the control in these two forms synchronized? For the issues we discussed, there are two or ten forms that are not important, and the problem is the same.
The first method is relatively simple. In fact, it is even more simple than our direct use of the commission, I want to entrust sometimes give people a feeling of killing chickens with cow knife. First, I created a class that contains the properties I want to share with all the forms in the application (see figure 1). For example, MYDATA and MOREDATA have data that can be displayed for each form. I will go back to this class soon.
Second, as I mentioned earlier, two forms have been established with the same control (TXT1STDATA and TXT2NDDATA). You can refer to the layout of Figure 2. Both forms have exactly the same data, and I will soon explain why. Figure 2 Forms Layout
Below, I build a module named Modgeneral and join the following line of code:
Friend DataStuff As Dataclass
This line of code creates a friend variable for my new class Dataclass, allowing you to fully access the assembly, which means the complete application. Then I added the following code to FORM1 LOAD event:
DataSTuff = new dataclass me.txt1stdata.databindings.add ("text", datastuff, "mydata") me.txt2nddata.databindings.add ("Text", DataStuff, "moredata")
The first line creates a new example of Dataclass. The following two lines of code bind the data to the TextBox control. For this form, it is doing so!
Now, how do you let them synchronize with the data on Form2 and other forms? Add the following two lines to the form LOAD event of Form 2:
Me.txt1stdata.databindings.add ("text", DataStuff, "MyData") Me.txt2nddata.databindings.add ("Text", DataStuff, "Moredata")
This method is easy to ensure that almost any type of data on all forms is in synchronous state. You can simply bind the control on a class of the same instance, this is OK.
Now let's look at another method. I created a new form called FRMBASE. At this time, I put a TextBox (TXTNextData) and Label. I want the application to share this TextBox and Label, and I hope that they will keep synchronization between them, so I rebuild this project. By inheritance from the new FRMBase, I created Form1 and Form2, so they inherited all new controls. But how can I keep these controls synchronized? At this time, you must write a code to achieve this effect, which is multiplexed in a single class, which is multiplexed by simply calling a function.
The code in Figure 3 shows this called Modgeneral Module. Its first task is to define two variables: MyForms and LocalNextData. MyForms is a collection that will contain a list of forms I want to synchronize. LocalNextData variables will store all the data I want to display in the form. Note that these variables can be rested in a certain class rather than a module. The AddForm process comes from MODGENERAL, with a form instance parameter, and add it to the MyForms collection. I will use this collection in the UpdateControlsNextData process to determine which forms are updated. AddForm also calls UpdateControlsNextData to make sure a new form is updated with the correct data.
Other codes in MODGENERAL are nextddata properties. These attributes of the SET Accessor update localnextdata and also call UpdateControlSNextData to synchronize all forms. At this time, all I need to do is to set NextData when you want to change it, and all forms will be updated by calling UpdateControlSNextData. The third method is to customize the link, it is the essence of the second method. I created it to get the flexibility to process more form controls. For example, I just want to track and handle some forms that contain controls that must be synchronized. This method also allows me to define the synchronization control and only process the form of these controls.
I added another module for this approach (MODGENERALV2), as shown in FIGURE 4. The module includes a collection of myFormStOut, which contains all I want synchronous forms. This module has a new array, which provides a list of controls I want to synchronize. The array is defined as follows:
Private controlstoupdate () as string = {"txtcustomer", "txtaddress", "txtname"}
This module has a new replacement version of AddForm called AddFormTOUPDATE. This method works with addform, but now it only adds a form that has a control in one or more controlstoupDate arrays, so only those forms containing specific controls are in the update collection. It allows me to call this function from each form. If I decide to add a particular control in the future, it will be automatically added to the form list. I only need to make a small change for the form code to be realized.
This module also contains the UpdateControlsonAllForms process, which performs updates. Instead of an application-level variable used in the previous method, I now use the concept of the main form. So I can copy the value of that form to all other forms in the collection. UpdateControlsonAllForms is actually a set of simple for ... nexts loop all controls that travers a form, find the controls that need to be updated and update them.
In order to achieve this in my form, I joined this line of code in the form of the LOAD event: AddFormTOUPDATE (ME)
Another optional method, I can add it to the constructor. This line of code will add the current form instance to a collection.
Let us now examine a single event process:
Private sub txt_leave (Byval e as system.eventargs) Handles Txtaddress.Leave, _ txtcustomer.leave, txtname.leave UpdateControlsonAllForms (me) End Sub
This code bundles all three controls I want to synchronize to the Leave events of TXTADDRESS, TXTCUSTOMER and TXTNAMEs to one event handle. At this time I can add a line of code to call UpdateControlsonAllForms. The ME is passed to the process call, causing other forms to synchronize with the form. Now I have three versions of code, they can synchronize the controls in the form, so I can choose. I may have used custom events that define an event in Dataclass and let each form book it. Then when this event is triggered, these forms can get new data from each event handle and set the appropriate control. But doing the amount of code required to do is less less than the control of the control than the first method. I can build a single process for updating and put the process in a module. I need to pass form instances to the process to implement updates. I can trigger this process with an event handle in the class. This process looks like this:
Sub UpdateControls (Byval thisform as frmbase) with thisform .txtNextData.text = localnextdata endh end sub
The ThisForm parameter is defined as a FRMBase type so that it can access IntelliSense and get a custom property of the form. Simply write it into Form will not display properties in FRMBase and its derived form.
Another choice is to use delegate. Of course, the commission can allow me to redirect the commission to the method of redirection to each form. If I use multicast mechanism, I can let each form handle the event and update the corresponding control. It sounds simple to establish such a function to establish such a function, but it is more troublesome and there is no practical value. In addition, the for ... next circulation with the third method