Home > Articles > Programming > Windows Programming

  • Print
  • + Share This
This chapter is from the book

This chapter is from the book

N-Tier Architecture

The Windows Forms system makes it easy to build n-tiered architectures. N-tiered architectures are those applications that are broken into multiple cooperating components. Although the various components, in the example programs, are compiled into the same program, they are logically separate and provide a framework for a more sophisticated distributed application.

The actual pattern employed, in the examples, is Model-View-Controller (MVC). The Windows Forms component is the View. There are a couple classes that are solely concerned with managing the data, which are the Model. A central object, referred to as the Controller, coordinates the View and Model portions. This section introduces where each portion of the program fits into the MVC pattern. Listing 16.3 shows the main form of an application named Cite Manager.

Listing 16.3 Cite Manager—Main Form: CiteManagerForm.cs

using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;

public class CiteManagerForm : Form
{
  private SiteManager citeMgr;

  private Container components;
  private Button  addButton;
  private Button  deleteButton;
  private Button  modifyButton;
  private Button  viewButton;
  private Label   selectLabel;

  public CiteManagerForm()
  {
    InitializeComponent();

    citeMgr = new SiteManager();
  }

  public override void Dispose()
  {
    base.Dispose();
    components.Dispose();
  }

  private void InitializeComponent()
  {
    components  = new Container();
    addButton  = new Button();
    deleteButton = new Button();
    modifyButton = new Button();
    viewButton  = new Button();
    selectLabel = new Label();

    addButton.Text   = "Add";
    addButton.Click  +=
      new EventHandler (addButton_Click);
    addButton.Location = new Point(94, 80);
    addButton.Size   = new Size(75, 23);
    addButton.TabIndex = 0;

    deleteButton.Text   = "Delete";
    deleteButton.Click  +=
      new EventHandler(deleteButton_Click);
    deleteButton.Location = new Point(94, 128);
    deleteButton.Size   = new Size(75, 23);
    deleteButton.TabIndex = 1;
    modifyButton.Text   = "Modify";
    modifyButton.Click  +=
      new EventHandler(modifyButton_Click);
    modifyButton.Location = new Point(94, 176);
    modifyButton.Size   = new Size(75, 23);
    modifyButton.TabIndex = 2;

    viewButton.Text   = "View";
    viewButton.Click  +=
      new EventHandler(viewButton_Click);
    viewButton.Location = new Point(94, 224);
    viewButton.Size   = new Size(75, 23);
    viewButton.TabIndex = 3;

    selectLabel.Text    = "Please Make a Selection:";
    selectLabel.Font    = new Font("Lucida Console",
                      12,
                      FontStyle.Italic);
    selectLabel.Location  = new Point(10, 32);
    selectLabel.Size    = new Size(246, 18);
    selectLabel.BorderStyle =
      System.Windows.Forms.BorderStyle.Fixed3D;
    selectLabel.AutoSize  = true;
    selectLabel.TabIndex  = 4;

    Text    = "Cite Manager";
    ClientSize = new Size (264, 273);
    Controls.Add(selectLabel);
    Controls.Add(modifyButton);
    Controls.Add(viewButton);
    Controls.Add(deleteButton);
    Controls.Add(addButton);
  }

  protected void deleteButton_Click (object sender,
                    System.EventArgs e)
  {
    DeleteForm df = new DeleteForm(citeMgr);
    df.ShowDialog(this);
  }

  protected void modifyButton_Click (object sender,
                    System.EventArgs e)
  {
    ModifyForm mf = new ModifyForm(citeMgr);

    mf.ShowDialog(this);
  }
  protected void viewButton_Click (object sender,
                   System.EventArgs e)
  {
    ViewForm vf = new ViewForm(citeMgr);

    vf.ShowDialog(this);
  }

  protected void addButton_Click (object sender,
                  System.EventArgs e)
  {
    AddForm af = new AddForm();

    DialogResult dlgRes = af.ShowDialog(this);

    switch (dlgRes)
    {
      case DialogResult.OK:
        citeMgr.AddSite(
          af.sitenameTextbox.Text,
          af.addressTextbox.Text,
          af.descriptionTextbox.Text);
        break;
      case DialogResult.Cancel:
        // do nothing
        break;
      default:
        break;
    }
  }

  public static void Main(string[] args)
  {
    Application.Run(new CiteManagerForm());
  }
}

Listing 16.3 declares a Form class, CiteManager, with a Label and four Button controls. It also has a SiteManager object to manage the data associated with each site. The CiteManager constructor initializes the controls by calling the InitializeComponents() method. Then it instantiates the cites object as a SiteManager.

After instantiating the Label and Button objects, the InitializeComponents() method proceeds to initialize each of these controls. Initialization of all buttons is similar, so we'll concentrate on the Add button as typical of the others.

Most controls have a Text property. The Add button's text property is set to "Add". This is the text that shows up on the front of the button. The next line sets the Add button's Click event. It uses the standard Windows Forms EventHandler delegate to encapsulate the event handler method. Every time the Add button is clicked, the addButton_Click() method is called. The Location property specifies where the upper left-hand corner of the button will be located on its parent form. It's set with a Point object. The Size property controls the width and height of a button. It's set with a Size object. Tab Indexes indicate the sequence of controls that get focus when the Tab key is pressed. When a form first starts up, Tab Index 0 gets the focus first. This is the Add button. If the Tab key is pressed again, focus transfers to the Delete button with Tab Index 1. Labels are meant to hold static information and are not operated on. Therefore, they won't receive focus, regardless of their Tab Index.

The Label control has a couple differences from the other controls on this form worth noting. First, its Font is set to something other than the default. This is done by instantiating a Font object. The three parameters to the Font constructor are the font name, size, and style. The style parameter is a member of the FontStyle enum. Most controls also have a border style. The Label's border style is set to Fixed3D by using the BorderStyle enum. This produces the sunken border effect on the label.

Finally, the CiteManager form's Text property is set to "Cite Manager". This changes the text in the main form's title bar. Every Form object has a Controls collection, which holds all of the form's controls and iterates through that list when laying out the form for display. Each Label and Button defined in this method is added to Controls by using the standard Collections Add() method syntax.

The deleteButton_click(), modifyButton_click(), and viewButton_click() methods are similar in operation. They instantiate their associated form objects and then call them. Each uses the ShowDialog() method. This pops up the appropriate form to be used as a modal dialog box. Alternatively, each of these forms could have been started with the Show() method. The difference is that the Show() method starts the form as an ordinary window, which doesn't have all the built-in functionality of a dialog box.

Note

Modal dialog boxes prevent interaction with any other part of a program while they are running. They must be dismissed before resuming operations on the rest of the program. On the other hand, Modeless dialog boxes permit users to interact with other parts of a program at the same time that the dialog is up and running. A good example of a modeless dialog box is the Find function of a word processor.

The addButton_click() method shows how to retrieve the results from a dialog box. It instantiates the AddForm object and calls the ShowDialog() method, just like the other event handler methods, but this retrieves the return value into a DialogResult field. The dlgRes field holds a DialogResult enum, which is used in a switch statement to determine the proper action to take. The only real action occurs when dlgRes equals DialogResult.OK. Then the program calls the AddSite() method of the citeMgr object to add a new site. The parameters for the AddSite() method call are obtained from the AddForm form. The AddForm form has three TextBox controls: sitenameTextbox, addressTextbox, and descriptionTextbox. The data is pulled out of each of these controls by calling their Text properties.

There is a method in the CiteManager class called Dispose(). The Windows Forms framework uses this to clean up system resources allocated during the session. This is the recommended method of cleaning up program resources.

The CiteManager class has the Main() method for this program. Its single task is to call the static Run() method of the System.Application class. The Run() method begins the program with a new instance of the CiteManager class. Figure 16.2 shows how the CiteManager form looks when run.

Figure 16.2 The Main screen of the Cite Manager program.

The SiteManager class is used extensively in this program. As the Controller component of this program, it coordinates input from the Windows Forms View components. The input is used to manage a collection of WebSite objects that are the primary data items, the Model component, of this program. Listings 16.4 and 16.5 show these classes and how they manage the data for the Cite Manager program.

Listing 16.4 The Site Manager Class: SiteManager.cs

using System;
using WebSites;

public class SiteManager {
  SiteList sites = new SiteList();

  public SiteManager()
  {
    this.sites = new WebSites.SiteList();
    this.sites[this.sites.NextIndex] = new WebSite
       ("Joe", "http://www.mysite.com", "Great Site!");
    this.sites[this.sites.NextIndex] = new WebSite
       ("Don", "http://www.dondotnet.com", "okay.");
    this.sites[this.sites.NextIndex] = new WebSite
       ("Bob", "http://www.bob.com", "No http://");
  }

  public WebSite this[int index]
  {
    get
    {
      return sites[index];
    }
  }

  public int Count
  {
    get
    {
      return sites.NextIndex;
    }
  }

  public void AddSite(string siteName,
            string url,
            string description)
  {
    sites[sites.NextIndex] = new WebSite
       (siteName, url, description);
  }

  public void DeleteSite(int index)
  {
    if (index <= sites.NextIndex)
      sites.Remove(index);
  }

  public void ModifySite()
  {
    Console.WriteLine("Modifying Sites.");
  }
}

The SiteManager class in Listing 16.4 provides logic that properly manages the manipulation of data in the sites container. The implementation of this class is similar to classes by the same name in earlier chapters. Changes were made to support the requirements of this program. Listing 16.5 shows the classes of the WebSites namespace. These classes comprise the Model components of this program.

Listing 16.5 The WebSites Namespace and Classes: WebSites.cs

namespace WebSites
{
  using System;
  using System.Collections;

  public class WebSite
  {
    const string http   = "http://";
    public static readonly string currentDate =
      new DateTime().ToString();
    string siteName;
    string url;
    string description;

    public WebSite()
      : this("No Site", "no.url", "No Description") {}

    public WebSite(string newSite)
      : this(newSite, "no.url", "No Description") {}

    public WebSite(string newSite, string newURL)
      : this(newSite, newURL, "No Description") {}

    public WebSite(string newSite,
            string newURL,
            string newDesc)
    {
      SiteName  = newSite;
      URL     = newURL;
      Description = newDesc;
    }

    public override string ToString()
    {
      return siteName + ", " +
            url + ", " +
        description;
    }

    public override bool Equals(object evalString)
    {
      return this.ToString() == evalString.ToString();
    }

    public override int GetHashCode()
    {
      return this.ToString().GetHashCode();
    }

    protected string ValidateUrl(string url)
    {
      if (!(url.StartsWith(http)))
      {
        return http + url;
      }
      return url;
    }

    public string SiteName
    {
      get
      {
        return siteName;
      }
      set
      {
        siteName = value;
      }
    }

    public string URL
    {
      get
      {
        return url;
      }
      set
      {
        url = ValidateUrl(value);
      }
    }

    public string Description
    {
      get
      {
        return description;
      }
      set
      {
        description = value;
      }
    }
  }

  public class SiteList
  {
    protected ArrayList sites;

    public SiteList()
    {
      sites = new ArrayList();
    }

    public int NextIndex
    {
      get
      {
        return sites.Count;
      }
    }

    public WebSite this[int index]
    {
      get
      {
        if (index > sites.Count)
          return (WebSite)null;

        return (WebSite) sites[index];
      }
      set
      {
        if ( index < 10 )
          sites.Add(value);
      }
    }

    public void Remove(int element)
    {
      sites.RemoveAt(element);
    }
  }
}

Listing 16.5 shows the classes of the WebSites namespace. This namespace exists to provide specialized support for data relating to the definition of a Web site. It has a SiteList class, providing access to WebSite objects. The WebSite class is also a member of the WebSites namespace. It is used extensively in the Cite Managers program. The rest of this section shows the various Windows Forms that this program uses to manipulate WebSite data held in SiteList containers. Listing 16.6 shows how to add a new Web site to the program.

Listing 16.6 A Windows Form for Adding a Web Site Listing: AddForm.cs

using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;

public class AddForm : Form
{
  private Container components;
  public TextBox  descriptionTextbox;
  public TextBox  addressTextbox;
  public TextBox  sitenameTextbox;
  private Button  cancelButton;
  private Button  okButton;
  private Label   descriptionLabel;
  private Label   addressLabel;
  private Label   sitenameLabel;

  public AddForm()
  {
    InitializeComponent();
  }

  public override void Dispose()
  {
    base.Dispose();
    components.Dispose();
  }

  private void InitializeComponent()
  {
    components     = new Container();
    okButton      = new Button();
    cancelButton    = new Button();
    sitenameLabel   = new Label();
    addressLabel    = new Label();
    descriptionLabel  = new Label();
    sitenameTextbox  = new TextBox();
    addressTextbox   = new TextBox();
    descriptionTextbox = new TextBox();

    okButton.Text     = "OK";
    okButton.Location   = new Point(120, 168);
    okButton.Size     = new Size(75, 23);
    okButton.DialogResult = DialogResult.OK;
    okButton.TabIndex   = 6;

    cancelButton.Text     = "Cancel";
    cancelButton.Location   = new Point(256, 168);
    cancelButton.Size     = new Size(75, 23);
    cancelButton.DialogResult = DialogResult.Cancel;
    cancelButton.TabIndex   = 7;

    sitenameLabel.Text   = "Site Name:";
    sitenameLabel.Location = new Point(24, 24);
    sitenameLabel.Size   = new Size(64, 20);
    sitenameLabel.TextAlign =
      ContentAlignment.MiddleRight;
    sitenameLabel.TabIndex = 0;

    sitenameTextbox.Location = new Point(96, 24);
    sitenameTextbox.Size   = new Size(344, 20);
    sitenameTextbox.TabIndex = 3;

    addressLabel.Text   = "Address:";
    addressLabel.Location = new Point(24, 72);
    addressLabel.Size   = new Size(64, 20);
    addressLabel.TextAlign =
      ContentAlignment.MiddleRight;
    addressLabel.TabIndex = 1;

    addressTextbox.Location = new Point(96, 72);
    addressTextbox.Size   = new Size(344, 20);
    addressTextbox.TabIndex = 4;

    descriptionLabel.Text   = "Description:";
    descriptionLabel.Location = new Point(24, 120);
    descriptionLabel.Size   = new Size(64, 20);
    descriptionLabel.TextAlign =
      ContentAlignment.MiddleRight;
    descriptionLabel.TabIndex = 2;

    descriptionTextbox.Location = new Point(96, 120);
    descriptionTextbox.Size   = new Size(344, 20);
    descriptionTextbox.TabIndex = 5;

    Text    = "Add Form";
    ClientSize = new Size(464, 213);
    Controls.Add(descriptionTextbox);
    Controls.Add(addressTextbox);
    Controls.Add(sitenameTextbox);
    Controls.Add(cancelButton);
    Controls.Add(okButton);
    Controls.Add(descriptionLabel);
    Controls.Add(addressLabel);
    Controls.Add(sitenameLabel);
  }
}

This listing shows the Add form from the Cite Manager application. There are two significant new items to learn from this form. First is that this form has TextBox controls. The only properties being set on them are the Location, Size, and TabIndex. It's possible to set their Text property, but in this case it doesn't fit the purpose of the application. One way to explicitly blank out the text of a TextBox is by setting its Text property to "". Figure 16.3 shows what this form looks like.

Figure 16.3 The Add Cite screen of the Cite Manager program.

The other interesting item on this form is the OK and Cancel buttons. They have their DialogResult properties set with DialogResult.OK and DialogResult.Cancel enums, respectively. This does several things. It establishes default behavior when the form is started with a ShowDialog() call. Pressing the Enter or Return key invokes the OK button. Similarly, pressing the Esc key invokes the Cancel button. When either button is clicked or its behavior is invoked, the dialog box closes and returns the DialogResult associated with that button. This is a lot of functionality that isn't available when the form is invoked with the Show() method.

Another interesting aspect of this form is that the TextAlign properties of the Label controls are set with the ContentAlignment.MiddleRight enum. This causes their text to have vertical alignment in the middle of the label and horizontal alignment on the right side of the label. Next is the DeleteForm, shown in Listing 16.7.

Listing 16.7 A Windows Form for Deleting a Web Site Listing: DeleteForm.cs

using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;

public class DeleteForm : Form
{
  SiteManager citeMgr;

  private Container components;
  private Panel   separator;
  private Button  okButton;
  private Button  cancelButton;
  private Button  deleteButton;
  private ListBox  deleteListbox;

  public DeleteForm(SiteManager citeMgr)
  {
    InitializeComponent();

    this.citeMgr = citeMgr;

    for (int i=0;i < this.citeMgr.Count; i++)
    {
      deleteListbox.Items.Insert(i, this.citeMgr[i].ToString());
    }
  }

  public override void Dispose()
  {
    base.Dispose();
    components.Dispose();
  }

  private void InitializeComponent()
  {
    components  = new Container();
    okButton   = new Button();
    cancelButton = new Button();
    deleteButton = new Button();
    deleteListbox = new ListBox();
    separator   = new Panel();

    okButton.Text     = "OK";
    okButton.Location   = new Point(40, 216);
    okButton.Size     = new Size(75, 23);
    okButton.DialogResult = DialogResult.OK;
    okButton.TabIndex   = 2;

    cancelButton.Text   = "Cancel";
    cancelButton.Location = new Point (176, 216);
    cancelButton.Size   = new Size (75, 23);
    cancelButton.TabIndex = 3;

    deleteButton.Text   = "Delete";
    deleteButton.Click  += new EventHandler (deleteButton_Click);
    deleteButton.Location = new Point(104, 152);
    deleteButton.Size   = new Size(75, 23);
    deleteButton.TabIndex = 1;

    deleteListbox.Location = new Point(8, 8);
    deleteListbox.Size   = new Size(280, 134);
    deleteListbox.TabIndex = 0;

    separator.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
    separator.Location  = new Point(8, 184);
    separator.Size    = new Size(280, 4);
    separator.TabIndex  = 4;

    Text    = "Delete Form";
    ClientSize = new Size (296, 261);

    Controls.Add(separator);
    Controls.Add(cancelButton);
    Controls.Add(okButton);
    Controls.Add(deleteButton);
    Controls.Add(deleteListbox);
  }

  protected void deleteButton_Click (object sender, System.EventArgs e)
  {
    citeMgr.DeleteSite(deleteListbox.SelectedIndex);
    deleteListbox.Items.Remove(deleteListbox.SelectedIndex);
    deleteListbox.Invalidate();
  }
}

Listing 16.7 shows the DeleteForm of the Cite Manager application. The new control on this form is the ListBox. The DeleteForm constructor loads the deleteListbox control by calling the Insert() method of its Items collection property. The first parameter is the zero-based position in the ListBox to locate the entry. The second parameter is the text to be displayed. This example uses the ToString() method of the WebSite object that is returned by the citeMgr indexer. The appearance of the DeleteForm is shown in Figure 16.4.

Figure 16.4 The Delete Cite screen of the Cite Manager program.

This example also uses a Panel as a separator. The straight-line effect is achieved by specifying a height of 3 when setting the Size property of the separator control. Another interesting item in this form is the omission of a setting for the Cancel button's DialogResult property. This causes nothing to happen when the Cancel button is clicked. If the DialogResult property had been set appropriately, such an action would close the dialog box and return with a DialogResult.Cancel enum value. Listing 16.8 shows implementation of the ComboBox and Group controls.

Listing 16.8 A Windows Form for Modifying a Web Site Listing: ModifyForm.cs

using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;

public class ModifyForm : Form
{
  SiteManager citeMgr;

  private Container components;
  private Label   selectionLabel;
  private ComboBox selectionCombobox;
  private Button  changeButton;
  private Label   sitenameLabel;
  private Label   addressLabel;
  private Label   descriptionLabel;
  private TextBox  sitenameTextbox;
  private TextBox  addressTextbox;
  private TextBox  descriptionTextbox;
  private GroupBox groupBox;
  private Button  okButton;
  private Button  cancelButton;

  public ModifyForm(SiteManager citeMgr)
  {
    InitializeComponent();

    this.citeMgr = citeMgr;

    for (int i=0;i < this.citeMgr.Count; i++)
    {
      selectionCombobox.Items.Insert(i, this.citeMgr[i].ToString());
    }

    selectionCombobox.SelectedIndex = 0;
}

  public override void Dispose()
  {
    base.Dispose();
    components.Dispose();
  }

  private void InitializeComponent()
  {
    components     = new Container();
    selectionLabel   = new Label();
    selectionCombobox = new ComboBox();
    changeButton    = new Button();
    sitenameLabel   = new Label();
    addressLabel    = new Label();
    descriptionLabel  = new Label();
    sitenameTextbox  = new TextBox();
    addressTextbox   = new TextBox();
    descriptionTextbox = new TextBox();
    groupBox     = new GroupBox();
    okButton      = new Button();
    cancelButton    = new Button();

    selectionLabel.Text   = "Select Cite:";
    selectionLabel.Location = new Point(32, 24);
    selectionLabel.Size   = new Size(64, 21);
    selectionLabel.TextAlign = ContentAlignment.MiddleRight;
    selectionLabel.TabIndex = 9;

    selectionCombobox.Text         = "comboBox1";
    selectionCombobox.SelectedIndexChanged += new
_EventHandler(selectionCombobox SelectedIndexChanged);
    selectionCombobox.Location       = new Point(104, 24);
    selectionCombobox.Size         = new Size(232, 21);
    selectionCombobox.TabIndex       = 8;

    changeButton.Text   = "Change";
    changeButton.Click  += new EventHandler(changeButton_Click);
    changeButton.Location = new Point(368, 24);
    changeButton.Size   = new Size(75, 23);
    changeButton.TabIndex = 10;

    sitenameLabel.Text   = "Site Name:";
    sitenameLabel.Location = new Point(32, 80);
    sitenameLabel.Size   = new Size(64, 20);
    sitenameLabel.TextAlign = ContentAlignment.MiddleRight;
    sitenameLabel.TabIndex = 0;

    addressLabel.Text   = "Address:";
    addressLabel.Location = new Point(32, 128);
    addressLabel.Size   = new Size(64, 20);
    addressLabel.TextAlign = ContentAlignment.MiddleRight;
    addressLabel.TabIndex = 1;

    descriptionLabel.Text   = "Description:";
    descriptionLabel.Location = new Point(32, 176);
    descriptionLabel.Size   = new Size(64, 20);
    descriptionLabel.TextAlign = ContentAlignment.MiddleRight;
    descriptionLabel.TabIndex = 2;

    sitenameTextbox.Location = new Point(104, 80);
    sitenameTextbox.Size   = new Size(344, 20);
    sitenameTextbox.TabIndex = 5;
    addressTextbox.Location = new Point(104, 128);
    addressTextbox.Size   = new Size(344, 20);
    addressTextbox.TabIndex = 6;

    descriptionTextbox.Location = new Point(104, 176);
    descriptionTextbox.Size   = new Size(344, 20);
    descriptionTextbox.TabIndex = 7;

    groupBox.Text   = "Modified Data";
    groupBox.Location = new Point(16, 56);
    groupBox.Size   = new Size(456, 152);
    groupBox.TabStop = false;
    groupBox.TabIndex = 11;

    okButton.Text       = "OK";
    okButton.Location     = new Point(128, 224);
    okButton.Size       = new Size(75, 23);
    okButton.DialogResult   = DialogResult.OK;
    okButton.TabIndex     = 3;

    cancelButton.Text     = "Cancel";
    cancelButton.Location   = new Point(272, 224);
    cancelButton.Size     = new Size(75, 23);
    cancelButton.DialogResult = DialogResult.Cancel;
    cancelButton.TabIndex   = 4;

    Text    = "Modify Form";
    ClientSize = new System.Drawing.Size (488, 261);

    Controls.Add(changeButton);
    Controls.Add(selectionLabel);
    Controls.Add(selectionCombobox);
    Controls.Add(descriptionTextbox);
    Controls.Add(addressTextbox);
    Controls.Add(sitenameTextbox);
    Controls.Add(cancelButton);
    Controls.Add(okButton);
    Controls.Add(descriptionLabel);
    Controls.Add(addressLabel);
    Controls.Add(sitenameLabel);
    Controls.Add(groupBox);
  }

  protected void changeButton_Click (object sender, System.EventArgs e)
  {
    citeMgr.DeleteSite(selectionCombobox.SelectedIndex);
    citeMgr.AddSite(sitenameTextbox.Text, addressTextbox.Text,
_descriptionTextbox.Text);
    selectionCombobox.Items[selectionCombobox.SelectedIndex] = 
            citeMgr[selectionCombobox.SelectedIndex].ToString();
  }

  protected void selectionCombobox_SelectedIndexChanged
_(object sender, System.EventArgs e)
  {
    WebSites.WebSite cite = citeMgr[selectionCombobox.SelectedIndex];

    sitenameTextbox.Text  = cite.SiteName;
    addressTextbox.Text   = cite.URL;
    descriptionTextbox.Text = cite.Description;
  }
}

Listing 16.8 shows the ModifyForm of the Cite Manager application. Because of its interaction between controls and increased number of controls, this is probably the most complex of all the forms so far. This form enables a user to select a Web site from a ComboBox control (also known as drop-down list) and make changes to the entry. When the changes are complete, the user clicks the Change button. This makes the underlying changes to the data and then updates the ComboBox. Figure 16.5 shows what this form looks like.

Figure 16.5 The ModifyForm screen of the Cite Manager program.

The two new controls on this form are the ComboBox and GroupBox. The ComboBox, selectionCombobox, is initialized in the constructor of the ModifyForm class. A for loop iterates through the WebSite objects of the citeMgr object. The ComboBox itself is loaded differently than a ListBox control. It uses the Insert() method of the ComboBox Item property. Next, it selects the first item in the list by setting the SelectedIndex property to zero.

The selectionCombobox has its SelectedIndexChanged event loaded with a delegate referring to the selectionCombobox_SelectedIndexChanged() event handler method. This method uses the current index from the selectionCombobox and maps it to the corresponding WebSite index in the citeMgr object. Then it updates the corresponding TextBox controls with the value from the selected WebSite object.

The Change button has its Click event loaded with a delegate referring to the changeButton_Click event handler method. This method uses the current index from the selectionCombobox and maps it to the corresponding WebSite index in the citeMgr object. This index is used to first delete the site, and then add it back to the citeMgr object. Then it updates the selectionCombobox control with the modified entry from the citeMgr object.

The GroupBox control surrounds the three TextBox controls and their Labels. This helps organize the form and make it more intuitive to users. A GroupBox control is commonly used to surround radio buttons and return the mutually exclusive value when queried. Other controls are initialized similar to that described in previous forms in this section. The last form, shown in Listing 16.9, is for viewing the available Web sites.

Listing 16.9 A Windows Form for Viewing Web Site Listings: ViewForm.cs

using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;

public class ViewForm : Form
{
  private Container  components;
  private Button    cancelButton;
  private Button    okButton;
  private ColumnHeader nameColumnHeader;
  private ColumnHeader urlColumnHeader;
  private ColumnHeader descriptionColumnHeader;
  private ListView   viewListview;

  public ViewForm(SiteManager citeMgr)
  {
    string[] columns = new string[3];

    InitializeComponent();

    for (int i=0;i < citeMgr.Count; i++)
    {
      columns[0] = citeMgr[i].SiteName;
      columns[1] = citeMgr[i].URL;
      columns[2] = citeMgr[i].Description;

      ListViewItem list = new ListViewItem(columns);
      viewListview.Items.Add(list);
    }
  }

  public override void Dispose()
  {
    base.Dispose();
    components.Dispose();
  }

  private void InitializeComponent()
  {
    components       = new Container();
    okButton        = new Button();
    cancelButton      = new Button();
    nameColumnHeader    = new ColumnHeader();
    urlColumnHeader     = new ColumnHeader();
    descriptionColumnHeader = new ColumnHeader();
    viewListview      = new ListView();

    okButton.Text     = "OK";
    okButton.Location   = new Point(88, 224);
    okButton.Size     = new Size(75, 23);
    okButton.DialogResult = DialogResult.OK;
    okButton.TabIndex   = 1;

    nameColumnHeader.Text   = "Cite Name";
    nameColumnHeader.TextAlign = HorizontalAlignment.Left;
    nameColumnHeader.Width   = 87;

    urlColumnHeader.Text   = "Address";
    urlColumnHeader.TextAlign = HorizontalAlignment.Left;
    urlColumnHeader.Width   = 135;

    descriptionColumnHeader.Text   = "Description";
    descriptionColumnHeader.TextAlign = HorizontalAlignment.Left;
    descriptionColumnHeader.Width   = 255;

    cancelButton.Text     = "Cancel";
    cancelButton.Location   = new Point(232, 224);
    cancelButton.Size     = new Size(75, 23);
    cancelButton.DialogResult = DialogResult.Cancel;
    cancelButton.TabIndex   = 2;

    viewListview.Columns.AddRange(new ColumnHeader[3]
      {
        nameColumnHeader,
        urlColumnHeader,
        descriptionColumnHeader
      }
    );
    viewListview.Location      = new Point(8, 8);
    viewListview.Size        = new Size(368, 192);
    viewListview.Sorting      = SortOrder.Ascending;
    viewListview.View        = View.Details;
    viewListview.GridLines     = true;
    viewListview.TabIndex      = 0;

    Text    = "View Form";
    ClientSize = new System.Drawing.Size(384, 273);

    Controls.Add (okButton);
    Controls.Add (cancelButton);
    Controls.Add (viewListview);
  }
}

The most important addition to this form is the ListView control, viewListview. Implementation of the viewListview control requires two important items, setting up columns and loading the data in the proper columns. Figure 16.6 shows what this form looks like.

Figure 16.6 The ViewForm screen of the Cite Manager program.

Setting up columns requires creation of three ColumnHeader objects: nameColumnHeader, urlColumnHeader, and descriptionColumnHeader. They're declared and instantiated the same as all other controls. Initialization of each ColumnHeader object involves setting its Text, TextAlignment, and Width properties. These three items affect the appearance of the column header on the screen.

The data is loaded into the viewListview control in the ViewForm constructor. This process is different from what is used for both the ListBox and ComboBox controls. There is an array of three strings, columns, for holding each column of WebSite data. In the for loop the columns array is loaded with the SiteName, URL, and Description properties of the current WebSite object. The columns array is used to create a ListViewItem object. Then the ListViewItem object is added to the Items property of the ListView control, viewListview. Listing 16.10 has the command line to compile a complete program from the preceding files.

Listing 16.10 Command Line for The Cite Manager Program

csc /out:citemgr.exe /r:System.Windows.Forms.DLL
_/r:System.Drawing.DLL CiteManagerForm.cs
_AddForm.cs DeleteForm.cs ModifyForm.cs
_ViewForm.cs SiteManager.cs WebSites.cs
  • + Share This
  • 🔖 Save To Your Account