September 28th, 2007
A common question that comes up rather often in VB discussion forums is how to pass data between forms. One of the common solutions offered are to use global variables in one way or another, for example, creating a module specifically for holding these values. These methods have all the typical problems with associated with globals. Another common strategy is to make the desired data available via properties on the forms. This can work in some cases but also can lead to undesirable interdependencies between forms. However, there is another approach that is often overlooked.
This article is about this overlooked strategy, overloading the New, Show or ShowDialog methods of forms. The reason this gets overlooked is that it isn’t obvious, particularly to someone who is new to programming or those who’ve transitioned from VB6. Forms get thought of as a special case because they contain a lot of generated code. But, actually, behind the scenes, they’re just another class in the application. And, like other classes, we can adapt them to our needs by overloading their base methods.
As with other classes with no explicit New method, a parameter-less New method of a form is automatically generated by the .NET compilation process. If we want to add our own overload method, we just add it to the code for it to our form. Here’s what it should look like:
Public Sub New(ByVal customerOrder As Order) Me.InitializeComponent() LoadOrder(customerOrder) End Sub
In this example, we’re passing in an order object to our new form. Note that we call the InitializeComponent method first to create the controls on the form. This method is generated by VB.NET and is located in the [form name].Designer.vb file that contains a partial class definition for our form. Once the controls are created, we can then call our routine to load data into the controls.
When you define your own New method you will lose the default parameter-less New method and thus lose the VB.NET created default instance. To restore the default instance, add your own Public Sub New() as shown here:
Public Sub New() ' This call is required by the Windows Form Designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. End Sub
In Visual Studio, if you just type in the first line and press enter the rest will be generated for you. If you don’t add this routine, you will need to explicitly create instances of the form using your New method as in this example.
Dim frmCustomerOrder As New frmOrder(CurrentOrder)
You can use this way to insure that the form is properly loaded with data before it is displayed.
Show, as you probably know, displays the form modelessly and does not return a value. This function comes with one overload which allows you to specify the owing window/form. To continue our example, let’s add a Show method that takes our order object.
Public Overloads Sub Show(ByVal customerOrder As Order) If customerOrder Is Nothing Then 'load up order defaults Else 'load from parameter End If MyBase.Show() End Sub
Notice at the end we call the form’s base class to show the form. If you don’t have this line, then the form will not be displayed.
While the stock methods don’t return a value, did you know that you can write a version of this method that returns a value? You can. Here’s an example:
Public Overloads Function Show(ByVal OrderID As Guid, ByVal viewOnly As Boolean) As Boolean If LoadCustomerOrder(OrderID) Then SetupControls(viewOnly) MyBase.Show() Return True Else Return False End If End Function
In this example, we return a True if the order is found and the form is loaded but a False if the order ID isn’t found. Remember that processing doesn’t stop at the MyBase.Show() to wait for user input but continues onward.
ShowDialog shows the target form modally and, in its built-in methods, it returns a Windows.Forms.DialogResult value. Here’s an example of overloading it
Public Overloads Function ShowDialog(ByRef newCustomerOrder As Order) As Windows.Forms.DialogResult newCustomerOrder = New Order 'load up order defaults Return MyBase.ShowDialog() End Function
In this case we’re passing in an order object by reference so that the dialog can modify it and return it and we’re returning a DialogResult like the other overloads. Also, just like with the show method, we need to call the base class to show the dialog.
Note, however, that we don’t need to return the DialogResult value, we can return anything we want, as seen in this code that returns an order object.
Public Overloads Function ShowDialog(ByVal orderID As Guid) As Order Dim ExistingCustomerOrder As New Order(orderID) 'load up order defaults If ExistingCustomerOrder.OrderDetail IsNot Nothing Then If MyBase.ShowDialog() = Windows.Forms.DialogResult.OK Then Return ExistingCustomerOrder Else Return Nothing End If Else Return Nothing End If End Function
It is probably best for consistency in most cases to return the same value as the default methods though.
That’s how you can pass values around between forms without having to use global variables (or work-alikes) or properties. Let me know if you have any questions, additions, or corrections by leaving me a comment.
Rate This Article: