Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Visual CSharp 2005 Recipes (2006) [eng]

.pdf
Скачиваний:
48
Добавлен:
16.08.2013
Размер:
4.04 Mб
Скачать

218 C H A P T E R 7 W I N D O W S F O R M S

private void listView1_ItemActivate(object sender, EventArgs e)

{

//Get information from the linked FileInfo object and display

//it using MessageBox.

ListViewItem item = ((ListView)sender).SelectedItems[0]; FileInfo file = (FileInfo)item.Tag;

string info = file.FullName + " is " + file.Length + " bytes.";

MessageBox.Show(info, "File Information");

}

[STAThread]

public static void Main(string[] args)

{

Application.Run(new Recipe07_02());

}

}

}

Usage

Figure 7-2 shows how the example will look when run.

Figure 7-2. Storing data in the Tag property

7-3. Process All the Controls on a Form

Problem

You need to perform a generic task with all the controls on the form. For example, you may need to retrieve or clear their Text property, change their color, or resize them.

Solution

Iterate recursively through the collection of controls. Interact with each control using the properties and methods of the base Control class.

C H A P T E R 7 W I N D O W S F O R M S

219

How It Works

You can iterate through the controls on a form using the Control.ControlCollection object obtained from the Form.Controls property. The ControlCollection includes all the controls that are placed directly on the form surface. However, if any of these controls are container controls (such as GroupBox, Panel, or TabPage), they might contain more controls. Thus, it’s necessary to use recursive logic that searches the Controls collection of every control on the form.

The Code

The following example demonstrates the use of recursive logic to find every TextBox on a form and clears the text they contain. When a button is clicked, the code tests each control in the form’s ControlCollection to determine whether it is a TextBox by using the typeof operator.

using System;

using System.Windows.Forms;

namespace Apress.VisualCSharpRecipes.Chapter07

{

public partial class Recipe07_03 : Form

{

public Recipe07_03()

{

//Initialization code is designer generated and contained

//in a separate file using the C# 2.0 support for partial

//classes.

InitializeComponent();

}

// The event handler for the button click event.

private void cmdProcessAll_Click(object sender, System.EventArgs e)

{

ProcessControls(this);

}

private void ProcessControls(Control ctrl)

{

//Ignore the control unless it's a textbox. if (ctrl.GetType() == typeof(TextBox))

{

ctrl.Text = "";

}

//Process controls recursively.

//This is required if controls contain other controls

//(for example, if you use panels, group boxes, or other

//container controls).

foreach (Control ctrlChild in ctrl.Controls)

{

ProcessControls(ctrlChild);

}

}

[STAThread]

public static void Main(string[] args)

{

Application.Run(new Recipe07_03());

220 C H A P T E R 7 W I N D O W S F O R M S

}

}

}

7-4. Track the Visible Forms in an Application

Problem

You need access to all of the open forms that are currently owned by an application.

Solution

Iterate through the FormCollection object that you get from the static property OpenForms of the

Application object.

How It Works

In .NET Framework 2.0, Windows Forms applications automatically keep track of the open forms that they own. This information is accessed through the Application.OpenForms property, which returns a FormCollection object containing a Form object for each form the application owns. You can iterate through the FormCollection to access all Form objects or obtain a single Form object using its name (Form.Name) or its position in the FormCollection as an index.

The Code

The following example demonstrates the use of the Application.OpenForms property and the FormCollection it contains to manage the active forms in an application. The example allows you to create new forms with specified names. A list of active forms is displayed when you click the Refresh List button. When you click the name of a form in the list, it is made the active form.

Because of the way the FormCollection works, more than one form may have the same name. If duplicate forms have the same name, the first one found will be activated. If you try to retrieve

a Form using a name that does not exist, null is returned. The following is the code for the application’s main form.

using System;

using System.Windows.Forms;

namespace Apress.VisualCSharpRecipes.Chapter07

{

public partial class Recipe07_04 : Form

{

public Recipe07_04()

{

//Initialization code is designer generated and contained

//in a separate file using the C# 2.0 support for partial

//classes.

InitializeComponent();

}

// Override the OnLoad method to show the initial list of forms. protected override void OnLoad(EventArgs e)

{

C H A P T E R 7 W I N D O W S F O R M S

221

//Call the OnLoad method of the base class to ensure the Load

//event is raised correctly.

base.OnLoad(e);

// Refresh the list to display the initial set of forms. this.RefreshForms();

}

// A button click event handler to create a new child form. private void btnNewForm_Click(object sender, EventArgs e)

{

//Create a new child form and set its name as specified.

//If no name is specified, use a default name.

Recipe07_04Child child = new Recipe07_04Child();

if (this.txtFormName.Text == String.Empty)

{

child.Name = "Child Form";

}

else

{

child.Name = this.txtFormName.Text;

}

// Show the new child form. child.Show();

}

//List selection event handler to activate the selected form based on

//its name.

private void listForms_SelectedIndexChanged(object sender, EventArgs e)

{

//Activate the selected form using its name as the index into the

//collection of active forms. If there are duplicate forms with the

//same name, the first one found will be activated.

Form form = Application.OpenForms[this.listForms.Text];

//If the form has been closed, using its name as an index into the

//FormCollection will return null. In this instance, update the

//list of forms.

if (form != null)

{

// Activate the selected form. form.Activate();

}

else

{

// Display a message and refresh the form list. MessageBox.Show("Form closed; refreshing list...",

"Form Closed"); this.RefreshForms();

}

}

//A button click event handler to initiate a refresh of the list of

//active forms.

private void btnRefresh_Click(object sender, EventArgs e)

222 C H A P T E R 7 W I N D O W S F O R M S

{

RefreshForms();

}

// A method to perform a refresh of the list of active forms. private void RefreshForms()

{

//Clear the list and repopulate from the Application.OpenForms

//property.

this.listForms.Items.Clear();

foreach (Form f in Application.OpenForms)

{

this.listForms.Items.Add(f.Name);

}

}

[STAThread]

public static void Main(string[] args)

{

Application.Run(new Recipe07_04());

}

}

}

The following is the code for the child forms you create by clicking the New Form button.

using System;

using System.Windows.Forms;

namespace Apress.VisualCSharpRecipes.Chapter07

{

public partial class Recipe07_04Child : Form

{

public Recipe07_04Child()

{

InitializeComponent();

}

//Override the OnPaint method to correctly display the name of the

//form.

protected override void OnPaint(PaintEventArgs e)

{

//Call the OnPaint method of the base class to ensure the Paint

//event is raised correctly.

base.OnPaint(e);

// Display the name of the form. this.lblFormName.Text = this.Name;

}

// A button click event handler to close the child form. private void btnClose_Click(object sender, EventArgs e)

{

this.Close();

}

}

}

C H A P T E R 7 W I N D O W S F O R M S

223

Notes

Versions 1.0 and 1.1 of the .NET Framework do not provide any way of determining which forms are currently owned by an application. (The one exception is MDI applications, as described in recipe 7-5.) If you want to determine which forms exist or which forms are displayed, or you want one form to call the methods or set the properties of another form, you will need to keep track of form instances on your own.

For tracking small numbers of forms, one useful approach is to create a static class consisting of static members. Each static member holds a reference to a specific Form. If you have many forms you need to track, such as in a document-based application where the user can create multiple instances of the same form, one per document, a generic collection such as

a System.Collections.Generic.Dictionary<string,Form> is very useful. This lets you map a Form object to a name.

Whichever approach you take, each Form object should register itself with the tracker class when it is first created. A logical place to put this code is in the Form.OnLoad method. Conversely, when the Form object is closed, it should deregister itself with the tracker class. Deregistration should occur in the OnClosing or OnClosed method of the Form class.

Using either of these approaches, any code that requires access to a Form object can obtain a reference to it from the members of the tracker class, and even invoke operations on the Form instance directly through the tracker class if you are sure the Form object exists.

7-5. Find All MDI Child Forms

Problem

You need to find all the forms that are currently being displayed in an MDI application.

Solution

Iterate through the forms returned by the MdiChildren collection property of the MDI parent.

How It Works

The .NET Framework includes two convenient shortcuts for managing the forms open in MDI applications: the MdiChildren and the MdiParent properties of the Form class. The MdiParent property of any MDI child returns a Form representing the containing parent window. The MdiChildren property returns an array containing all of the MDI child forms.

The Code

The following example presents an MDI parent window that allows you to create new MDI children by clicking the New item on the File menu. Each child window contains a label, which displays the date and time when the MDI child was created, and a button. When the button is clicked, the event handler walks through all the MDI child windows and displays the label text that each one contains. Notice that when the example enumerates the collection of MDI child forms, it converts the generic Form reference to the derived Recipe07-05Child form class so that it can use the LabelText property. The following is the Recipe07-05Parent class.

using System;

using System.Windows.Forms;

namespace Apress.VisualCSharpRecipes.Chapter07

{

224 C H A P T E R 7 W I N D O W S F O R M S

// An MDI parent form.

public partial class Recipe07_05Parent : Form

{

public Recipe07_05Parent()

{

//Initialization code is designer generated and contained

//in a separate file using the C# 2.0 support for partial

//classes.

InitializeComponent();

}

// When the New menu item is clicked, create a new MDI child. private void mnuNew_Click(object sender, EventArgs e)

{

Recipe07_05Child frm = new Recipe07_05Child(); frm.MdiParent = this;

frm.Show();

}

[STAThread]

public static void Main(string[] args)

{

Application.Run(new Recipe07_05Parent());

}

}

}

The following is the Recipe07-05Child class.

using System;

using System.Windows.Forms;

namespace Apress.VisualCSharpRecipes.Chapter07

{

// An MDI child form.

public partial class Recipe07_05Child : Form

{

public Recipe07_05Child()

{

//Initialization code is designer generated and contained

//in a separate file using the C# 2.0 support for partial

//classes.

InitializeComponent();

}

//When a button on any of the MDI child forms is clicked, display the

//contents of a each form by enumerating the MdiChildren collection. private void cmdShowAllWindows_Click(object sender, EventArgs e)

{

foreach (Form frm in this.MdiParent.MdiChildren)

{

//Cast the generic Form to the Recipe07_05Child derived class

//type.

Recipe07_05Child child = (Recipe07_05Child)frm; MessageBox.Show(child.LabelText, frm.Text);

}

}

C H A P T E R 7 W I N D O W S F O R M S

225

// On load, set the MDI child form's label to the current date/time. protected override void OnLoad(EventArgs e)

{

//Call the OnLoad method of the base class to ensure the Load

//event is raised correctly.

base.OnLoad(e);

label.Text = DateTime.Now.ToString();

}

// A property to provide easy access to the label data. public string LabelText

{

get { return label.Text; }

}

}

}

Usage

Figure 7-3 shows how the example will look when run.

Figure 7-3. Getting information from multiple MDI child windows

7-6. Save Configuration Settings for a Form

Problem

You need to store configuration settings for a form so that they are remembered the next time that the form is shown.

226 C H A P T E R 7 W I N D O W S F O R M S

Solution

Use the .NET Framework 2.0 Application Settings functionality, which is configurable at design time in Visual Studio.

How It Works

The Application Settings functionality in .NET Framework 2.0 provides an easy-to-use mechanism through which you can save application and user settings used to customize the appearance and operation of a Windows Forms application. You configure Application Settings through the Properties panel of each Windows control (including the main Windows Form) in your application. By expanding the ApplicationSettings property and clicking the ellipsis (three dots) to the right of (PropertyBinding), you can review and configure Application Settings for each property of the active control. See Figure 7-4 for an example.

Figure 7-4. Configuring Application Settings in Visual Studio

When you configure a new Application Setting for a control’s property, you must assign it a name, a default value, and a scope.

C H A P T E R 7 W I N D O W S F O R M S

227

The name allows you to both access the setting programmatically and reuse the Application Setting across multiple controls.

The default value is used if the application cannot obtain a value from a configuration file at runtime.

The scope is either User or Application.

Settings with an Application scope are stored in the application’s configuration file (usually located in the same folder as the application assembly) and are read-only. The benefit of an Application scope is that you can change configuration settings by editing the configuration file without needing to recompile the application. Settings with a User scope are read-write by default and are stored as part of the user’s Windows profile in a file named after the executing assembly.

When you configure your application to use Application Settings, Visual Studio actually autogenerates a wrapper class that provides access to the configuration file information, regardless of whether it is scoped as Application or User. The class is named Settings and implements the Singleton pattern (discussed in recipe 13-10); the singleton instance is accessed through Settings.Default. This class contains properties with names matching each of the Application Setting names you configured for your controls’ properties. The controls will automatically read their configuration at startup, but you should store configuration changes prior to terminating your application by calling the Settings.Default.Save method.

The Code

The following example shows how to update and save Application Settings at runtime.

using System;

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

using Apress.VisualCSharpRecipes.Chapter07.Properties;

namespace Apress.VisualCSharpRecipes.Chapter07

{

public partial class Recipe07_06 : Form

{

public Recipe07_06()

{

//Initialization code is designer generated and contained

//in a separate file using the C# 2.0 support for partial

//classes.

InitializeComponent();

}

private void Button_Click(object sender, EventArgs e)

{

//Change the color of the textbox depending on which button

//was pressed.

Button btn = sender as Button;

if (btn != null)

{

//Set the background color of the textbox textBox1.BackColor = btn.ForeColor;

//Update the application settings with the new value. Settings.Default.Color = textBox1.BackColor;

}

}

Соседние файлы в предмете Программирование на C++