Home > Articles > Programming > Windows Programming

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

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020