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

Pro Visual C++-CLI And The .NET 2.0 Platform (2006) [eng]-1

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

358 C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

Figure 9-14 shows what RichText.exe looks like when you execute it.

Figure 9-14. The simple RTF editor in action

The Selection Controls

The three common selection controls, ListBox, ComboBox, and CheckedListBox, are the last of the more basic controls provided by the .NET Framework class library that you will cover in this chapter. Each of the controls represents a selectable scrolling list of items.

When you create a selection control, you provide it with a collection of values for it to display. Each value within the collection has a unique index. The control keeps track of these indices for you, along with their associated values. All you have to do is handle selection events sent by the selection controls or query the control for which a value or values have been selected, either by value or index.

Selection controls are helpful when you want to select from a list of items of a “reasonable” size. “Reasonable,” though, is a very relative term and it depends on what the user is selecting and where the data is coming from (fetching 300 rows from a local hard disk is different than fetching them from a mainframe in another country). For example, a list of 50 items may seem excessive in a selection control if there is no rhyme or reason to it, but it is just right when you are looking for a state in America.

All of the selection controls inherit from the abstract class ListControl. This provides a common set of properties and methods from which to build upon. Selection controls have the capability to display lists originating from sources that implement the IList interface. The functionality is provided by the ListControl’s property, DataSource. You will see an example of this when you cover ADO.NET in Chapter 12.

Here is a list of some of the most common properties found in the ListControl class and thus inherited by the ListBox, ComboBox, and CheckListBox controls:

DataSource is an Object that implements the IList interface, frequently an Array or DataSet, which represents the items that make up the control. The default is null, which means no DataSource is being used.

C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

359

SelectedIndex is an Int32 that represents the zero-based index of the currently selected item. If no index is selected, then –1 will be returned.

SelectedValue is an Object that represents the value of the currently selected item as specified by the control data source’s ValueMember. If the ValueMember is not specified, then the ToString() value is returned.

ValueMember is a String that represents the property of the control’s data source to use as the value. The default is an empty String (and not null), meaning that it uses the ToString() value.

The ListBox is truly just a selection list, whereas the ComboBox is a combination of a ListBox and a TextBox. The CheckListBox, on the other hand, is a combination of a ListBox and a CheckBox. In fact, the CheckListBox inherits directly from ListBox and thus only indirectly from ListControl.

ListBox

The ListBox control is a simple scrollable list of items from which a user can select one or more items, depending on the SelectionMode of the ListBox. Four modes are available:

SelectionMode::None: No items can be selected.

SelectionMode::One: Only one item can be selected at a time.

SelectionMode::MultiSimple: More than one item can be selected.

SelectionMode::MultiExtended: More than one item can be selected. The method of selecting the multiple items uses the Shift and Ctrl keys to allow for swifter selection of items.

The ListBox control provides a number of additional properties from the ListControl to configure the control and organize, find, and select the data within:

Items is a ListBox::ObjectCollection that represents the collection of items within the control. The ObjectCollection allows you to do things such as add and remove items from the ListBox. Note that this method of providing items to the ListBox is not the same as using a DataSource. If you use a DataSource, you cannot manipulate the items in the ListBox using the ObjectCollection.

MultiColumn is a Boolean that represents whether the control can be broken into multiple columns. The default is false.

SelectedIndices is a ListBox::SelectedIndexCollection that represents the collection of zero-based indices of currently selected items within the control.

SelectedItems is a ListBox::SelectedObjectCollection that represents the collection of currently selected items within the control.

Sorted is a Boolean that represents whether the control is automatically sorted. The default is false.

Text is a String that represents the value of the currently selected item. If you set the value of the Text property, then the ListBox searches itself for an item that matches the Text property and selects that item.

The ListBox control also provides a number of additional methods:

ClearSelected() deselects all selected items in the control.

FindString() finds the first item that starts with a given String.

FindStringExact() finds the first item that exactly matches a given String.

360 C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

GetSelected() determines if a given item is currently selected.

SetSelected() selects the items at the given index.

Sort() sorts the items in the control.

Listing 9-13 shows how to transfer selected items between two different lists. The ListBox on the left is sorted and is a MultiExtended list, whereas the one on the right is not sorted and is a

MultiSimple list.

Listing 9-13. Transferring Items Between ListBoxes

#pragma once

namespace

ListTransfers

{

 

using

namespace System;

using

namespace System::ComponentModel;

using

namespace System::Collections;

using

namespace System::Windows::Forms;

using

namespace System::Data;

using

namespace System::Drawing;

public ref class Form1 : public System::Windows::Forms::Form

{

public:

Form1(void)

{

InitializeComponent();

}

protected:

~Form1()

{

if (components)

{

delete components;

}

}

private:

System::Windows::Forms::ListBox^ LBDest; System::Windows::Forms::Button^ bnR2L; System::Windows::Forms::Button^ bnL2R; System::Windows::Forms::ListBox^ LBOrg; System::Windows::Forms::Label^ label2; System::Windows::Forms::Label^ label1;

System::ComponentModel::Container ^components;

C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

361

#pragma region Windows Form Designer generated code

void InitializeComponent(void)

{

this->LBDest = (gcnew System::Windows::Forms::ListBox()); this->bnR2L = (gcnew System::Windows::Forms::Button()); this->bnL2R = (gcnew System::Windows::Forms::Button()); this->LBOrg = (gcnew System::Windows::Forms::ListBox()); this->label2 = (gcnew System::Windows::Forms::Label()); this->label1 = (gcnew System::Windows::Forms::Label()); this->SuspendLayout();

//

//LBDest

this->LBDest->FormattingEnabled = true; this->LBDest->Location = System::Drawing::Point(213, 46);

this->LBDest->Name = L"LBDest"; this->LBDest->SelectionMode =

System::Windows::Forms::SelectionMode::MultiSimple; this->LBDest->Size = System::Drawing::Size(134, 134);

this->LBDest->TabIndex = 10; this->LBDest->DoubleClick +=

gcnew System::EventHandler(this, &Form1::LBDest_DoubleClick);

//bnR2L

//

this->bnR2L->Location = System::Drawing::Point(167, 108); this->bnR2L->Name = L"bnR2L";

this->bnR2L->Size = System::Drawing::Size(33, 20); this->bnR2L->TabIndex = 9;

this->bnR2L->Text = L"<=="; this->bnR2L->Click +=

gcnew System::EventHandler(this, &Form1::bnR2L_Click);

//

//bnL2R

this->bnL2R->Location = System::Drawing::Point(167, 80); this->bnL2R->Name = L"bnL2R";

this->bnL2R->Size = System::Drawing::Size(33, 20); this->bnL2R->TabIndex = 8;

this->bnL2R->Text = L"==>"; this->bnL2R->Click +=

gcnew System::EventHandler(this, &Form1::bnL2R_Click);

//LBOrg

//

this->LBOrg->FormattingEnabled = true; this->LBOrg->Items->AddRange(gcnew cli::array< System::Object^>(10)

{L"System", L"System::Collections", L"System::Data",

L"System::Drawing", L"System::IO", L"System::Net", L"System::Threading", L"System::Web", L"System::Windows::Forms", L"System::Xml"});

362 C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

this->LBOrg->Location = System::Drawing::Point(20, 46); this->LBOrg->Name = L"LBOrg"; this->LBOrg->SelectionMode =

System::Windows::Forms::SelectionMode::MultiExtended; this->LBOrg->Size = System::Drawing::Size(133, 134); this->LBOrg->Sorted = true;

this->LBOrg->TabIndex = 6; this->LBOrg->DoubleClick +=

gcnew System::EventHandler(this, &Form1::LBOrg_DoubleClick);

//

//label2

this->label2->AutoSize = true;

this->label2->Location = System::Drawing::Point(213, 17); this->label2->Name = L"label2";

this->label2->Size = System::Drawing::Size(104, 13); this->label2->TabIndex = 7;

this->label2->Text = L"Unsorted Multisimple";

//label1

//

this->label1->AutoSize = true;

this->label1->Location = System::Drawing::Point(20, 17); this->label1->Name = L"label1";

this->label1->Size = System::Drawing::Size(107, 13); this->label1->TabIndex = 5;

this->label1->Text = L"Sorted Multiextended";

//

// Form1

//

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(367, 196); this->Controls->Add(this->LBDest); this->Controls->Add(this->bnR2L); this->Controls->Add(this->bnL2R); this->Controls->Add(this->LBOrg); this->Controls->Add(this->label2); this->Controls->Add(this->label1);

this->Name = L"Form1";

this->Text = L"List Box Transfers"; this->ResumeLayout(false); this->PerformLayout();

}

#pragma endregion

private:

System::Void LBOrg_DoubleClick(System::Object^ sender, System::EventArgs^ e)

{

C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

363

//Add Selected item to other ListBox

//Then remove item from original

if (LBOrg->SelectedItem != nullptr)

{

LBDest->Items->Add(LBOrg->SelectedItem); LBOrg->Items->Remove(LBOrg->SelectedItem);

}

}

System::Void LBDest_DoubleClick(System::Object^ sender, System::EventArgs^ e)

{

//Add Selected item to other ListBox

//Then remove item from original

if (LBDest->SelectedItem != nullptr)

{

LBOrg->Items->Add(LBDest->SelectedItem); LBDest->Items->Remove(LBDest->SelectedItem);

}

}

System::Void bnL2R_Click(System::Object^ sender, System::EventArgs^ e)

{

//Add all Selected items to other ListBox

//Then remove all the items from original array<Object^>^ tmp =

gcnew array<Object^>(LBOrg->SelectedItems->Count); LBOrg->SelectedItems->CopyTo(tmp, 0); LBDest->Items->AddRange(tmp);

for (int i = 0; i < tmp->Length; i++) LBOrg->Items->Remove(tmp[i]);

}

System::Void bnR2L_Click(System::Object^ sender, System::EventArgs^ e)

{

//Add all Selected items to other ListBox

//Then remove all the items from original array<Object^>^ tmp =

gcnew array<Object^>(LBDest->SelectedItems->Count); LBDest->SelectedItems->CopyTo(tmp, 0); LBOrg->Items->AddRange(tmp);

for (int i = 0; i < tmp->Length; i++) LBDest->Items->Remove(tmp[i]);

}

};

}

The code is pretty straightforward. It creates two ListBoxes and configures them using their properties. There are a couple of things you need to pay attention to in Listing 9-13. First, when handling the double-click event for a list, make sure that an item is actually selected by checking the SelectedItem for a nullptr value before trying to work with the SelectedItem. This is because doubleclicking an area of the list that is not an item generates an event with no selection.

364 C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

The second thing to watch out for is removing items from a list using the SelectedItems property. The SelectedItems property does not create a copy of the items selected; instead, it uses the original items. Thus, if you try to remove items from a list such as the following:

// This code DOES NOT work

for (Int32 i = 0; i < LBDest->SelectedItems->Count; i++)

{

LBDest->Items->Remove(LBDest->SelectedItems->Item[i]);

}

not all the selected items get removed—in fact, only half do. What is happening is that

LBDest->SelectedItems->Count decreases when you call LBDest->Items->Remove() because the

SelectedItems enumeration is decreasing in size at the same time as the ListBox entries are. My solution was to create a copy of the SelectedItems and then use that instead of SelectedItems directly:

// This DOES work

array<Object^>^ tmp = gcnew array<Object^>(LBDest->SelectedItems->Count); LBDest->SelectedItems->CopyTo(tmp, 0);

for (int i = 0; i < tmp->Count; i++) LBDest->Items->Remove(tmp[i]);

Figure 9-15 shows what ListTransfers.exe looks like when you execute it.

Figure 9-15. Transferring items between list boxes

ComboBox

The ComboBox control is a combination of a ListBox control with a TextBox control attached to the top. The ListBox control provides a quick click response, and the TextBox control allows the user to type in an answer.

There are three different DropDownStyles of ComboBox:

ComboBoxStyle::Simple: The list is always expanded and the text field can be edited.

ComboBoxStyle::DropDown: The list starts collapsed but can be expanded and the text field can be edited.

ComboBoxStyle::DropDownList: The list starts collapsed but can be expanded and the text field only accepts Strings that are part of the selection list. (This style of ComboBox does not allow responses that are not part of the list.)

Like all other controls, the ComboBox provides several properties and methods to support the functionality of the control. You will probably recognize that these members are half TextBox and half ListBox in nature. Some of the common members unique to the ComboBox are as follows:

C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

365

DroppedDown is a Boolean that represents whether the list portion of the control has been expanded.

MaxDropDownItems is an Int32 that represents the maximum number of items that can be visually displayed in the list portion of the control. This number can range from 1 to 100. Note that this is not the same as the total items in the control, which is limited to the memory of the computer, though I doubt you will ever create a list that large (unless of course you accidentally create an infinite loop).

MaxLength is an Int32 that represents the maximum length of the text box portion of the control.

Select() is a method that selects a specified range of text within the text box portion of the control.

SelectAll() is a method that selects all the text in the text box portion of the control.

SelectionLength is an Int32 that represents the length of the selected text within the text box portion of the control.

SelectionStart is an Int32 that represents the zero-based starting position of the selected text within the text box portion of the control.

Listing 9-14 shows that you can keep all three ComboBox style controls in sync. Selecting an item in one control will automatically update the other two. If you type an entry in the text box area, the other two controls are updated appropriately. Note that if you type in a value that is not on the selection list, then the DropDownList style control does not update.

Listing 9-14. Synchronizing ComboBoxes

#pragma once

namespace

SyncCombos

{

 

using

namespace System;

using

namespace System::ComponentModel;

using

namespace System::Collections;

using

namespace System::Windows::Forms;

using

namespace System::Data;

using

namespace System::Drawing;

public ref class Form1 : public System::Windows::Forms::Form

{

public:

Form1(void)

{

InitializeComponent();

PopulateLists();

}

protected:

~Form1()

{

if (components)

{

delete components;

}

}

366 C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

private:

System::Windows::Forms::ComboBox^ ddlist; System::Windows::Forms::ComboBox^ simple; System::Windows::Forms::ComboBox^ ddown;

System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code

void InitializeComponent(void)

{

this->ddlist = (gcnew System::Windows::Forms::ComboBox()); this->simple = (gcnew System::Windows::Forms::ComboBox()); this->ddown = (gcnew System::Windows::Forms::ComboBox()); this->SuspendLayout();

//

//ddlist

this->ddlist->DropDownStyle = System::Windows::Forms::ComboBoxStyle::DropDownList;

this->ddlist->FormattingEnabled = true; this->ddlist->Location = System::Drawing::Point(300, 14);

this->ddlist->Name = L"ddlist";

this->ddlist->Size = System::Drawing::Size(121, 21); this->ddlist->TabIndex = 5;

this->ddlist->SelectedIndexChanged +=

gcnew System::EventHandler(this, &Form1::ddlist_Change);

//simple

//

this->simple->DropDownStyle = System::Windows::Forms::ComboBoxStyle::Simple;

this->simple->FormattingEnabled = true; this->simple->Location = System::Drawing::Point(154, 11); this->simple->Name = L"simple";

this->simple->Size = System::Drawing::Size(122, 117); this->simple->TabIndex = 4; this->simple->SelectedIndexChanged +=

gcnew System::EventHandler(this, &Form1::simple_Change); this->simple->TextChanged +=

gcnew System::EventHandler(this, &Form1::simple_Change);

//

// ddown

//

this->ddown->FormattingEnabled = true; this->ddown->Location = System::Drawing::Point(12, 14); this->ddown->MaxDropDownItems = 3; this->ddown->MaxLength = 10;

this->ddown->Name = L"ddown";

this->ddown->Size = System::Drawing::Size(121, 21); this->ddown->TabIndex = 3; this->ddown->SelectedIndexChanged +=

gcnew System::EventHandler(this, &Form1::ddown_Change);

C H A P T E R 9 B A S I C W I N D O W S F O R M S A P P L I C A T I O N S

367

this->ddown->TextChanged +=

gcnew System::EventHandler(this, &Form1::ddown_Change);

//

// Form1

//

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(433, 138); this->Controls->Add(this->ddlist); this->Controls->Add(this->simple); this->Controls->Add(this->ddown);

this->Name = L"Form1";

this->Text = L"Synchronized Combo boxing"; this->ResumeLayout(false);

}

#pragma endregion

private:

void PopulateLists()

{

// Item to be placed in all ComboBoxes array<Object^>^ ddItems = gcnew array<Object^> {

L"oranges", L"cherries", L"apples",

L"lemons", L"bananas", L"grapes"

}; ddown->Items->AddRange(ddItems); simple->Items->AddRange(ddItems); ddlist->Items->AddRange(ddItems);

}

System::Void ddown_Change(System::Object^ sender, System::EventArgs^ e)

{

// Update simple and dropdownlist with dropdown text simple->Text = ddown->Text;

ddlist->SelectedItem = ddown->Text;

}

System::Void simple_Change(System::Object^ sender,System::EventArgs^ e)

{

// Update dropdown and dropdownlist with simple text ddown->Text = simple->Text;

ddlist->SelectedItem = simple->Text;

}

System::Void ddlist_Change(System::Object^ sender,System::EventArgs^ e)

{

// Update simple and dropdown with dropdownlist SelectedText ddown->SelectedItem = ddlist->SelectedItem; simple->SelectedItem = ddlist->SelectedItem;

}

};

}