The answer is simple if you've done it and understand it but complex if you're just starting at it.
The "right" way to go about it would be to go read some articles about Presentation Model patterns; MVC is common in WinForms and they usually use MVVM in WPF. But if you're struggling with "How do I share information between UserControls?" you need to start smaller.
It makes me really sad that no one really teaches dependency management because it's often a harder problem than writing the rest of the program. It's something you're supposed to just figure out and it's actually very tricky. Here's a mini-tutorial in an informal style. It's going to sneakily teach you what Presentation Model patterns are all about while it's at it.
Think about classes in your program like you would little boxes with machinery inside. Consider a radio. It's got a knob for tuning that determines the station and a knob for the volume. It's also got a button for turning it on and off. We can represent it in code like this:
Code:
Class Radio
Public Property Station As Double
Public Property Volume As Double
Public Sub TurnOn()
Public Sub TurnOff()
End Class
Think about how you tell the radio what to do. You can turn the volume knob, turn the tuner knob, or push the power button. You can imagine what a form for this might look like (pretending that there's a knob control available.) But... normally you're taught to throw everything into a form. that is to say, most people would write code like this:
Code:
Class Form1
Inherits Form
Private _volume As Double
...
Sub VolumeKnob_ValueChanged(...) Handles VolumeKnob.ValueChanged
_volume = VolumeKnob.Value
End Sub
End Class
That's how most WinForms code's written; you've got a variable to represent a control and you sync it with the control property. Most people forego the variable and just use the control property directly. I call this the "ball of mud" development style because all of the code is glommed into a few really big files. Why's this bad? Let's get back to it.
What's happening there is Form1 isn't
representing a radio. Form1
is a radio. It sounds like a subtle difference until Form2 needs to have a radio too. Oops; your only option is copy and paste. So it's better to use that Radio class from earlier:
Code:
Class Form1
Inherits Form
Private _radio as New Radio()
...
Sub VolumeKnob_ValueChanged(...) Handles VolumeKnob.ValueChanged
_radio.Volume = VolumeKnob.Value
End Sub
End Class
Now Form1
has a radio, and the knobs manipulate the radio. If Form2 wants a radio, it can create one. Or it can get Form1's. Say you want Form1 to be able to open a Form2 that shares the same radio. Here's one way to design Form2 to facilitate that:
Code:
Class Form2
Inherits Form
Public Property Radio As Radio
End Class
For it to share Form1's radio, Form1 can set the Radio property:
Code:
' (In Form1:)
Sub ShowOtherForm()
Dim frm As New Form2()
frm.Radio = _radio
frm.Show()
End Sub
Taking it further, maybe 10 controls want to share the same Radio. It might be inconvenient for it to be a private detail of Form1. In applications like that, you might have some more global class that keeps track of the radio. The business of "Who owns each object, and how do the things that need those objects get them?" is called "dependency management". It's probably one of the most important factors in software development, and screwing it up is what leads to programs that are hard to maintain.
In short, these are the things that make up practically all modern application development methodologies:
- You should strive to make small classes that do one thing.
- Gluing several small classes together is the right way to do multiple things in one class.
- Classes communicate with each other via properties and method calls; usually passing other classes to each other.
- Figuring out who owns what class and how they communicate is the hardest part of a large application, and screwing it up will cause you no end of grief.
To make it relevant to your question:
To make an application like that, I'd make some kind of "Page" base class to represent a control that can go in a pane of the application. Each control would expect to get fed some information and it would display that information; if it was supposed to give information back it'd do that in a standard format. I would not want Control A asking Control B for values; I'd rather Control A ask some overseer that happens to know about Control B. That way, when I want to remove Control B 6 weeks from now things are cleaner.