views:

57

answers:

2

I'm creating a reporting application, and our customers are going to need to generate some pretty big reports which require quite a bit of memory. Ive been in a re-factoring mood lately, so I was wondering what the best way to access the properties of another open form would be(The reporting viewer opens in a new form.) So far I have:

Dim form As MainSelections

form = My.Application.OpenForms(2)

yay or nay.

Thanks

*Edit - I should probably mention that what I need is a label, two date time pickers, 5 datagridviews and a few datasets. Those cotrols have the info I use for my parameters

+3  A: 

First, don't access a form's controls directly, its considered a bad practice, access dependent data through an interface instead:

(Warning: untested code and my VB-fu is rusty, but you should get the general idea)

public interface ILoginScreen
    Property Username as String with Get
    Property Password as String with Get
end interface

Implement the interface on your Form. (And make sure your interface does not return datatypes like TextBox, ComboBox, etc, that would defeat the purpose of the interface abstraction.)

Second, don't access dependencies through global state like the OpenForms collection, pass your dependencies to your objects through a constructor instead.

So if your Reports form depends on your login screen (or any other screen), you should have a constructor which accepts an ILoginScreen implementation:

public sub New(loginScreen as ILoginScreen)
    me.LoginScreen = loginScreen
end sub

And instantiate your reports form as such:

dim reportScreen as new ReportScreen(Me)
'passes self as ILoginScreen implementation

According to the OP in the comments:

Actually what I need is a label, two date time pickers, 5 datagridviews and a few datasets. Those cotrols have the info I use for my parameters.

Evidently the OP is passing these controls as report parameters. Probably creating and implementing an interface is excessive for his needs, but the general principle of dependency injection is correct.

Pass your data into your Report form's constructor:

class Report
    public sub New(start as DateTime, end as DateTime, label as String, _
        etc as Whatever)
end class

Please ensure you pass things like DateTimes, Strings, Integers, DataSets, etc -- or a typed object representing your parameters.

Don't pass DateTimePickers, TextBoxes, Comboboxes, DataGridViews, etc. Your report form shouldn't know or care that its start and end dates come from a DateTimePicker or not, it should only care that it actually has dates of some kind. Lazily passing form controls is a surefire way to enrage the next person who works on your code.

Juliet
I'm still a little new at this, so should i have a module containing the varibles then pass them into the Report form's constructor? I'm kinda confused.
broke
@broke: no, you don't need another module. Just create the ReportForm from your MainSelections form, make sure you call the constructor which takes your parameters: `new ReportForm(dtStartTime.SelectedDateTime, dtEndTime.SelectedDateTime, lblReportName.Text, [whatever other properties]).Show()`.
Juliet
Sorry for being a pest, but i think i got it now.In my MainSelections i have:Dim reportscreen As New ReportForm(lblNumber.Text) reportscreen.ShowDialog()Then in my ReportForm i have Public Sub New(ByVal reportnum As String) ' This call is required by the Windows Form Designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. End SubI can fill in the rest of the requirements like the datasets and all that. Am I on the right track?
broke
Yes, you're on the right track :)
Juliet
okay thanks man
broke
A: 

If your business layer has to manipulate a form's controls, or read data from them, it's often good practice to implement an abstraction layer, such as you would when using the MVP or MVC pattern.

A reporting application is quite a good case for MVP, because by decoupling the UI from the report generation logic, you create the ability to test the reports independently of the UI, or to generate those same reports in another application (perhaps a console app).

The idea is to separate the UI from the business logic by representing it (the UI) in the form of an interface, which you (the business layer) may or may not have an instance of at any given time.

But there's more to it than that - have a look at Model View Presenter.

Charles