Tuesday, April 3, 2012

Managing Data Among Multiple Forms (Part 2)

Part 1 here

In part 1 of this series, I looked at using default instances in VB and how that gives you direct access to controls on any form, anywhere, any time.  I also showed how you could simulate default instances in C#.  Default instances are a handy feature for beginners but I wouldn’t recommend their use to anyone who’s serious about programming.  They’re an easy way to start out though.

This instalment will describe the use of what’s commonly as global variables.  This is another technique that makes life easier for beginners but should generally be avoided because it’s not really architecturally sound.  I’ll cover it here though for completeness and because it is also an easy way to start out, when most of what you do will not be architecturally sound.

As the name suggests, global variables are intended to give global access, i.e. you can access them anywhere, any time.  Just like default form instances, the idea is that you don’t have to create an object explicitly in order to access them, which means that you’re not limited to accessing that object only where it’s created.  There are various ways that that can be achieved, but the simplest is to use a module in VB or the equivalent in C#, which is a static class.

We’ll use basically the same example as last time, transferring text from a TextBox on one form to a TextBox on another form and then back again.  This time though, instead of one form passing data to and retrieving data from the other form, each will deal only with the global variable.

So, first things first, let’s declare that global variable.  In VB, add a new module to your project and add the following code:

Module Module1

    'The text that will be transferred between TextBoxes.
    Public textBoxText As String

End Module
In C#, add a new class to your project and add the following code:

static class Class1
{
    // The text that will be transferred between TextBoxes.
    public static string textBoxText;
}
Notice the addition of the ‘static’ keyword to both the class and the field.  A static member is one that is a member of the class itself rather than each specific instance and a static class is one that can only have static members.  The class itself doesn’t actually have to be static but it’s the correct thing to do.
Set up the user interface as before, with a TextBox and a Button on Form1 and a TextBox on Form2.  Create a Click event handler for the Button on Form1 and add the following code:

VB
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    'Push the data to the global variable from the TextBox on this form.
    textBoxText = Me.TextBox1.Text

    'Show the second form as a modal dialogue.
    Using dialogue As New Form2
        dialogue.ShowDialog()
    End Using

    'Pull the data from the global variable to the TextBox on this form.
    Me.TextBox1.Text = textBoxText
End Sub
C#
private void button1_Click(object sender, EventArgs e)
{
    // Push the data to the global variable from the TextBox on this form.
    Class1.textBoxText = this.textBox1.Text;

    // Show the second form as a modal dialogue.
    using (Form2 dialogue = new Form2())
    {
        dialogue.ShowDialog();
    }

    // Pull the data from the global variable to the TextBox on this form.
    this.textBox1.Text = Class1.textBoxText;
}
Note that in both VB and C# I have included a ‘Using’/’using’ statement.  This is to create the dialogue and destroy it again after it’s been used.  I’m not using a default instance in the VB code to show that this technique of using global variables doesn’t depend on them.  Also note that the global variable is qualified with the class name in the C# code but it is not qualified with the module name in the VB code.  You can qualify module members in VB if you want to but the module name can be omitted, which is behaviour consistent with modules in VB6.

Now, create handlers for the Load and FormClosed events in Form2 and add this code:

VB
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    'Pull the data from the global variable to the TextBox on the this form.
    Me.TextBox1.Text = textBoxText
End Sub

Private Sub Form2_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
    'Push the data to the global variable from the TextBox on this form.
    textBoxText = Me.TextBox1.Text
End Sub

C#
private void Form2_Load(object sender, EventArgs e)
{
    // Pull the data from the global variable to the TextBox on the this form.
    this.textBox1.Text = Class1.textBoxText;
}

private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
    // Push the data to the global variable from the TextBox on this form.
    Class1.textBoxText = this.textBox1.Text;
}
That’s all we need.  You can now run the project and do as for the previous example.  Enter some text in the TextBox on Form1 and then click the Button and you’ll see that text appear in the TextBox on Form2.  Edit that text and close the form and you’ll see the new text appear in the TextBox on the first form.

Looking back at the code, you can see that neither form refers directly to the TextBox on other.  In fact, there’s no reference to Form1 at all in Form2.  Both forms use the global variable as an intermediary, with each form having no specific dependency on the other.

That’s it for this instalment on global variables.  In the next instalment, I’ll start looking at how to do things the “proper” way.

Part 3 here

No comments: