Creating the User Interface


Creating the user interface is generally the most time-consuming process when developing an application. First, you have to prototype the interface, then you have to build it, then you have to go back and rework it, and so on and so on. I introduce a few methods in this section to help you avoid (or at least lessen) the work necessary when building the user interface. At the beginning, though, there is slightly more work needed.

Two things every business application, regardless of the content of the application, needs to do are as follows: show lists of data and show data details for viewing and editing. Every developer has their own method of creating list screens and editing forms. This is great in that a developer can express their creativity, but the users tend to have a problem with it. They expect that if they are going to view one list, then every other list they view in the same application will have the same controls on the screen and will behave and look the same way. Consistency makes everyone happier and results in fewer calls to the help desk and fewer complaints by the user. No developer can probably honestly say they have not heard a user complain, "Why doesn't it work like this?" So, the key is consistency, and with consistency comes a lot less work on the part of the interface developer. To this end you will create two base forms, one for showing lists of information, the other for editing that information. All of the forms that you create afterward will inherit from one form or the other.

To being with, let's create the Multiple Document Interface (MDI) form that will serve as your framework.

Note

There has been a move in recent years to create Single Document Interface (SDI) applications. It is been my experience while developing for the enterprise that many users like to compare different things side by side and like to have multiple windows open. I see no need to move away from this paradigm as long as it is what my users want to see. After all, without users there can be no developers.

Double-click the Form1.vb class module in NorthwindTraders in the Solution Explorer. This brings up Form1 in the editor. Rename Form1.vb to frmMain.vb. Then, go to the Properties tab and change the IsMdiContainer to True. Change the WindowState property to Maximized, and change the name property of the form to frmMain. If you have the Task List visible, the following error will display:

 'Sub Main' was not found in 'NorthwindTraders.UserInterface.Form1'. 

To correct this error, double-click this entry in the Task List and select NorthwindTraders.frmMain from the Startup Object dialog box that appears and click OK. That removes the error.

Next, you add a test menu to your MDI container so that you can launch your forms from it for testing purposes. Add a MainMenu control to the form and add a single menu item called Test. The menu should look like the menu in Figure 3-7.


Figure 3-7: frmMain MainMenu Test MenuItem

Creating the ListBase Form

You can now start adding your base forms. As with VB 6, the best way to show lists of information is still with the listview control. In .NET, the listview control has been vastly improved so that you can format individual items and subitems independently of any other items on the row. This is an awesome capability that many of you who used VB 6 fought to try and make happen with custom controls and fancy Application Programming Interface (API) tricks that never worked very well. Add a new form to the NorthwindTraders project and call it frmListBase. To do this, right-click the NorthwindTraders project and select Add Add Windows Form and name it frmListBase.vb. When you are done adding controls to the form, it should look like the form in Figure 3-8.

click to expand
Figure 3-8: The completed frmListBase

Add the controls to the form as listed in Table 3-1.

Table 3-1: The ListBase Form Controls and Properties

Control

Control Name

Control Text

Label

Column:

Combobox

cboColumn

[Empty]

Label

Search For:

Textbox

txtSearch

[Empty]

Button [*]

btnFind

Listview

lvwList

Button

btnDelete

&Delete

Button

btnPrint

&Print

Button

btnAdd

&Add

Button

btnEdit

&Edit

Button

btnClose

&Close

ContextMenu

ctmListBase

N/A

ContextMenu

ctmEdit

&Edit

ContextMenu

ctmDelete

&Delete

Label

lblRecordCount

Record Count:

[*]You can find a binoculars image in the Visual Studio .NET folder \Common7\Graphics\Bitmaps\ Tlbr_W95 folder.

Next, set the properties for the different controls according to Table 3-2.

Table 3-2: Additional Control Properties

Control

Property

Value

lvwList

ContextMenu

ctmListBase

lvwList

FullRowSelect

True

lvwList

MultiSelect

False

lvwList

View

Details

cboColumn

DropDownStyle

DropDownList

frmListBase

MaximizeBox

False

txtSearch

Anchor

Top, Left, Right

btnFind

Anchor

Top, Right

lvwList

Anchor

Top, Left, Bottom, Right

lblRecordCount

Anchor

Left, Bottom

btnDelete

Anchor

Bottom, Right

btnPrint

Anchor

Bottom, Right

btnAdd

Anchor

Bottom, Right

btnEdit

Anchor

Bottom, Right

btnClose

Anchor

Bottom, Right

Caution

Although the users may want to have the ability to maximize a form, remember that in an MDI application, when one form is maximized, all of the forms are maximized. This has the undesirable effect of maximizing the edit screen even when you do not want it to be maximized.

Now, return to frmMain, double-click the test menu item to get to the code module, and add the following code above the Windows Forms Designer- generated code:

 Private mfrmListBase As frmListBase 

Then enter the following code in the MenuItem1_Click method:

 mfrmListBase = New frmListBase() mfrmListBase.MdiParent = Me mfrmListBase.Show() 

In .NET, you must use code to set a form as an MDI child, as you can see here. Also, remember that unlike VB 6, forms are now true objects. If you declare a form in a method and run it, when the method execution ends, so does your object's lifetime. In practical terms this means that unless you are displaying a form using the ShowDialog() method, you will need to declare it as a module-level variable.

You should now be able to run the application and click the Test menu item, which should cause your base list form to display. The controls on the form should remain in the correct position and move as the form is resized. In the next section, you will inherit from your base form so that you can actually load some data. Then you will come back and make some more changes to your base form.

Inheriting the ListBase Form

In the NorthwindTraders project, right-click the project and select Add Inherited Form. Call the form frmRegionList and click the Open button. An inheritance window will display, as shown in Figure 3-9.

click to expand
Figure 3-9: Inheritance Picker window

Double-click the frmListBase from the list of available forms. The new form will be displayed in the VS .NET IDE, as shown in Figure 3-10.

click to expand
Figure 3-10: frmRegionList form, inherited from the frmListBase form

Notice that all of the controls on the form now have a little blue arrow in the top-left corner. This denotes that these controls have been inherited.

Caution

When using inherited forms in the same application as the form you are inheriting from, the form you are inheriting from must be compiled before a subclassed form can be rendered. You may have to build the application before the subclassed form is displayed. Also, if you have a problem with your code in the base form, you will have numerous errors when you try to display your subclassed form in the design environment.

Change the form caption to read Region List. Next, add the following three lines to the top of the frmRegionList code module:

 Option Explicit On Option Strict On Imports NorthwindTraders.NorthwindUC 

Also, take note that the inherits line does not read System.Windows.Forms.Form. Instead, it now reads NorthwindTraders.frmListBase.

Tip

You do not have to add an inherited form using the Add Inherited Window menu item. You can simply add a Windows form and change the class from which the form inherits.

The RegionList Form

Add the following module-level reference to the frmRegionList class:

 Private mobjRegionMgr As RegionMgr 

Create a new method called LoadList by adding the code in Listing 3-18.

Listing 3-18: The LoadList Method

start example
 Private Sub LoadList()      Dim objRegion As Region      Dim objDictEnt As DictionaryEntry      lvwList.BeginUpdate()      If lvwList.Columns.Count = 0 Then           With lvwList                .Columns.Add("Region Description", CInt(.Size.Width / 1) - 8, _ HorizontalAlignment.Left)           End With      End If      lvwList.Items.Clear()      mobjRegionMgr = mobjRegionMgr.GetInstance      For Each objDictEnt In mobjRegionMgr           objRegion = CType(objDictEnt.Value, Region)           Dim lst As New ListViewItem(objRegion.ToString)           lst.Tag = objRegion.RegionID           lvwList.Items.Add(lst)      Next      lvwList.EndUpdate()      lblRecordCount.Text = "Record Count: " & lvwList.Items.Count End Sub 
end example

There are many things going on here, so let's start at the top. First you create a variable for a Region object and another variable for a DictionaryEntry object. As mentioned, the For..Each..Next loop used to loop through the RegionMgr class actually returns a DictionaryEntry object. The BeginUpdate method of the listview pauses the redrawing of the listview as you are adding objects to it. Next, you set up the listview by adding the correct number of columns and sizing them. Then you clear the listview and call the GetInstance method of RegionMgr object, which returns a reference to a fully loaded RegionMgr object. Next, you loop through the RegionMgr collection and add the text that you need to a listviewitem object. Notice that the first line of the For..Each..Next loop reads as follows:

 objRegion = CType(objDictEnt.Value, Region) 

To actually get the contents of the DictionaryEntry object, you need to access the value property and convert this to the object of the correct type. You store the ID for the Region object in the tag property of the listview item because it is easy to retrieve. Finally, you add the listviewitem to the listview, and after you are done adding all of your Region objects, you call the EndUpdate method of the listview, which allows the listview to redraw itself.

Lastly, you will call the LoadList method from the frmRegionList form constructor (this will be the last line of the constructor). To do this, expand the Windows Forms Designer-generated code region of the frmRegionList code module and change the Public Sub New constructor to look like the following:

 Public Sub New()      MyBase.New()      'This call is required by the Windows Form Designer.      InitializeComponent()      'Add any initialization after the InitializeComponent() call      LoadList() End Sub 

The reason why you are calling this from the constructor and not from the form load event is because you need to have the listview filled before you call the Load method of the base form. This will be explained when you implement the ability to search through the listview for a specific item (in the "Implementing the Find Functionality" section).

The final change you need to make before you test your region object is to change the reference in frmMain to point to your frmRegionList form instead of the frmListBase form. Change the code to read as follows:

 Private mfrmRegionList As frmRegionList Private Sub MenuItem1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem1.Click      Cursor = Cursors.WaitCursor      mfrmRegionList = New frmRegionList()      mfrmRegionList.MdiParent = Me      mfrmRegionList.Show()      Cursor = Cursors.Default End Sub 

Creating the Remoting Channel

You need to add one last bit of code to make this work. You need to create the channel to communicate with your remote objects. To do this, import the following two namespaces into frmMain:

 Imports System.Runtime.Remoting.Channels Imports System.Runtime.Remoting.Channels.Http 

These two namespaces contain the classes that facilitate the communication over a remoting channel. Add this module-level variable declaration to frmMain:

 Private chan As HttpChannel 

This is the actual channel that you will register with the ChannelServices object. Open the Windows Forms Designer-generated code region and locate the constructor. Then add the following code:

 'Add any initialization after the InitializeComponent() call Dim props As New Collections.Specialized.ListDictionary() props.Add("useDefaultCredentials", True) chan = New HttpChannel(props, New BinaryClientFormatterSinkProvider(), New _ BinaryServerFormatterSinkProvider()) ChannelServices.RegisterChannel(chan) 

This code does a couple of things. First it creates a ListDictionary object to which you can add properties recognized by the HttpChannel. The only property you are interested in here is the useDefaultCredentials property, which you set to True. This allows your Windows identity to be passed over the network to IIS in such a manner that IIS can impersonate your identity. Next, you declare the new channel, pass in your property dictionary, and specify that you want to serialize the data using a binary formatter. The last step to make this work is to register the channel with the ChannelServices object.

Finally, you need a way to unregister the channel when the user exits the application. To do this, enter the following code that will run when the application closes:

 Private Sub frmMain_Closed(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Closed      ChannelServices.UnregisterChannel(chan) End Sub 

Building and Deploying the Application

The final step you need to take is to actually build the assemblies. Select Build Build Solution from the main menu. You should see the following in the Output window at the bottom of the IDE:

 ---------------------- Done ----------------------     Build: 4 succeeded, 0 failed, 0 skipped 

At this point you need to go to the bin directory located under the NorthwindDC project folder and copy the NorthwindDC.dll and NorthwindShared.dll files to the c:\inetpub\wwwroot\Northwind\bin folder (or wherever you set this up in Chapter 2, "Building an N-Tier Application"). You should now be able to run the application by clicking the Run button (or F5 depending on the developer template you selected).

Click the Test menu item on the main menu. The window that appears should look identical to the window in Figure 3-11.

click to expand
Figure 3-11: The Region List from the Northwind database

Now that you have this working, it is time to start making some enhancements.




Building Client/Server Applications with VB. NET(c) An Example-Driven Approach
Building Client/Server Applications Under VB .NET: An Example-Driven Approach
ISBN: 1590590708
EAN: 2147483647
Year: 2005
Pages: 148
Authors: Jeff Levinson

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net