6.6. The List Box for Unformatted Output

Up to this point we have been directing our text to a console window. A somewhat more visually appealing alternative is to direct our output to the list box of a Windows Forms window. For example, Figure 6.12 displays the content of a text file directed into a simple form containing only a list box. As configured, the vertical and horizontal scrolling is added as needed. The program is virtually unchanged, although factored out into an independent function:

Figure 6.12. The Windows Forms List Box Window


private void
process_file( string file_name )
{
      StreamReader ifile = File.OpenText( file_name );

      string textline;
      int    lineCnt = 0;

      while (( textline = ifile.ReadLine()) != null )
      {
            thisForm.TheListBox.Items.Add( textline );
            if ( lineCnt++ == 0 )
                   thisForm.Text = textline;
      }
}

thisForm is the Form object representing our window. TheListBox is the ListBox control. I dragged the ListBox control onto the form, then resized both. Items represents the container in which elements of the list box are stored. Add() inserts an item at the end of the container. (The Text property of the form, recall, represents the title bar.)

Because we are using the window only as a display area rather than to capture and respond to events, I factored the processing of the file into a separate class. Inside the form constructor, I created an instance of the class, passing it a reference to the form. This is how the thisForm object is initialized.

When the designer generates its C# code, it creates the following general constructor for our Form1 object:

public Form1()
{
   //
   // required for Windows Forms designer support
   //
   InitializeComponent();

   //
   // TODO: add any constructor code after InitializeComponent()
   //
}

After changing the generic Form1 class name to ListboxForm and adding the creation and invocation of our class, the revised constructor looks like this:

public ListboxForm()
{
   InitializeComponent();

   processListbox proc = new processListbox( this );
   proc.process_file( @"c:fictionsword.txt" );
}

Of course, hard-coding the file name is not very flexible. One possible program extension to provide more flexibility is to add a text box for the user to enter the path of the file to display. An OK button event handler reads the text box text and invokes process_file(), passing in the file name:

protected void button1_Click (object sender, EventArgs e)
{
      if ( textBox1.Text.Length != 0 )
           proc.process_file( textBox1.Text );
}

Let's add a Clear button just to show how to empty the list box. To count how many items it holds, we invoke Count(). If it is not empty, we clear the items by invoking Clear():

protected void button3_Click (object sender, System.EventArgs e)
{
      if ( TheListBox.Items.Count != 0 )
           TheListBox.Items.Clear();
}

The other design change has to do with the idea of the lifetime of an object. Originally we defined proc within the form constructor:

public ListboxForm()
{
      InitializeComponent();

      processListbox proc = new processListbox( this );
      proc.process_file( @"c:fictionsword.txt" );
}

Recall from the code example earlier in this section that proc is a reference to the processListbox object allocated through the new expression. The lifetime of proc—that is, the extent of time it exists as a handle to a process Listbox class object—is the duration of the constructor invocation, during which time the list box is filled with items. Moreover, proc is visible only within that constructor. (We say that proc has scope local to the constructor.) There is no direct way to access proc from outside the constructor, as we attempt to do inside our button click event handler. Oops!

We have to extend both proc's accessibility and its lifetime. Minimally, our click event handler must be able to access proc. Potentially any method of the Form class may wish access to proc. To make it visible to any class method and to provide it with a lifetime coincident with that of the Form class, we simply declare proc to be a member of that class.

To introduce our own members within the Form class, we open up the C# text file generated by the designer. We then scroll down to find the control definitions generated by the form designer, and, following them, introduce our own—for example,

public class ListboxForm : Form
{
// these are generated by Windows Forms designer
   private System.ComponentModel.Container components;
   private System.Windows.Forms.Button button3;
   private System.Windows.Forms.Button button2;
   private System.Windows.Forms.Button button1;
   private System.Windows.Forms.TextBox textBox1;
   private System.Windows.Forms.Label label1;

// also generated by Windows Forms, but I renamed it
   private ListBox theListbox;

// OK: this is our member
    private processListbox proc;

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.176.99