позволяет определить индекс такого элемента. Коллекция может автоматически сортироваться, для этого достаточно задать значение
true свойства
Sorted, которым обладает список
ListBox.
Еще один способ задания элементов списка поддерживается свойством DataSource, значение которого позволяет указать источник данных, ассоциируемый со списком. Понятно, что этот способ является альтернативой коллекции, задаваемой свойством Items. Так что, если источник данных определен свойством DataSource, то нельзя использовать методы класса ObjectCollection — Add и другие для добавления или удаления элементов списка, — необходимо изменять сам источник данных.
Главное назначение элемента ListBox — предоставить пользователю возможность осуществлять выбор из отображаемых списком элементов. Свойство SeiectionMode позволяет указать, сколько элементов разрешается выбирать пользователю — один или несколько. Для работы с отобранными элементами имеется ряд свойств. SelectedItem и SeiectedIndex возвращают первый отобранный элемент и его индекс. Свойства SeiectedItems и SeiectedIndices возвращают коллекции, заданные классами SelectedObjectCollection и SelectedIndexCollection, которые дают возможность анализировать все отобранные пользователем объекты. Методы Contains и IndexOf позволяют определить, выбрал ли пользователь некоторый элемент. Добавлять или удалять элементы из этих коллекций нельзя.
Среди других методов и свойств ListBox — упомяну свойство MultiColumn, с помощью которого можно организовать показ элементов списка в нескольких столбцах; свойство HorizonalScrollBar, задающее горизонтальный скроллинг; методы BeginUpdate и EndUpdate, позволяющие повысить эффективность работы со списком. Все методы по добавлению и удалению элементов, стоящие после BeginUpdate, не будут приводить к перерисовке списка, пока не встретится метод EndUpdate.
У элемента управления ListBox большое число событий, с некоторыми из которых мы встретимся при рассмотрении примеров. Перейдем теперь к рассмотрению примеров работы с этим элементом управления и, как обещано, построим некоторый шаблон, демонстрирующий работу с двумя списками, когда пользователь может переносить данные из одного списка в другой и обратно. На рис. 24.4 показано, как выглядит форма, реализующая данный шаблон.
Рис. 24.4. Шаблон формы для обмена данными двух списков
На форме показаны два списка — listBox1 и listBox2, между которыми расположены две командные кнопки. Обработчик события Click первой кнопки переносит выбранную группу элементов одного списка в конец другого списка, (если включено свойство Sorted, то автоматически поддерживается сортировка списка). Переносимые элементы удаляются из первого списка. Вторая кнопка реализует операцию переноса всех элементов списка. Направление переноса — из левого списка в правый и обратно — задается заголовками (">", ">>") или ("<", "«"), изображенными на кнопках. Заголовки меняются автоматически в обработчиках события Enter, возникающих при входе в левый или правый списки — listBox1 или listBox2. Еще две командные кнопки, как следует из их заголовков, предназначены для закрытия формы с сохранением или без сохранения результатов работы пользователя. Таково общее описание шаблона. А теперь рассмотрим реализацию. Начнем с обработчиков события Enter наших списков:
private void listBox1_Enter(object sender, System.EventArgs e)
{
/*** Событие Enter у списка возникает при входе в список ***/
button1.Text = ">"; button2.Text =">>";
}
private void listBox2_Enter(object sender,
System.EventArgs e)
{
/*** Событие Enter у списка возникает при входе в список ***/
button1.Text = "<"; button2.Text ="<<";
}
Посмотрим, как устроены обработчики события Click для командных кнопок, осуществляющих перенос данных между списками:
private void button1_Click(object sender, System.EventArgs e)
{
/* Обработчик события Click кнопки "> <"
* Выборочный обмен данными между списками
* ListBox1 <-> ListBox2******************/
if(button1.Text == ">")
MoveSelectedItems(listBox1, listBox2);
else
MoveSelectedItems(listBox2, listBoxi);
}
private void button2_Click(object sender, System.EventArgs e)
{
/* Обработчик события Click кнопки ">> <<"
* Перенос всех данных одного списка в конец другого списка
* ListBox1 <-> ListBox2******************/
if (button2.Text == ">>")
MoveAllItems(listBox1, listBox2);
else
MoveAllItems(listBox2, listBox1);
}
Обработчики событий устроены достаточно просто — они вызывают соответствующий метод, передавая ему нужные аргументы в нужном порядке. Рассмотрим метод, переносящий множество отобранных пользователем элементов из одного списка в другой:
private void MoveSelectedItems(ListBox list1, ListBox list2)
{
/*** Выделенные элементы списка list1 ****
*** помещаются в конец списка List2 *****
*** и удаляются из списка list1 ********/
list2.BeginUpdate();
foreach (object item in listl.SelectedItems)
{
list2.Items.Add(item);
}
list2.EndUpdate();
ListBox.SelectedlndexCollection indeces = listl.Selectedlndices;
list1.BeginUpdate();
for (int i = indeces.Count -1; i>=0; i-)
{
lList1.Items.RemoveAt(indeces[i]);
}
list1.EndUpdate();
}
Некоторые комментарии к этому тексту. Заметьте, для добавления выделенных пользователем элементов к другому списку используется коллекция SelectedItems и метод Add, поочередно добавляющий элементы коллекции. Метод AddRange для добавления всей коллекции здесь не проходит:
list2.Items.AddRange(list1.SelectedItems);
поскольку нет автоматического преобразования между коллекциями ObjectCollection и SelectedObjectCollection.
Для удаления выделенных элементов из списка list1 используется коллекция индексов. Обратите внимание, при удалении элемента с заданным индексом из любой коллекции индексы оставшихся элементов автоматически пересчитываются. Поэтому удаление элементов происходит в обратном порядке, начиная с последнего, что гарантирует корректность оставшихся индексов.
Намного проще устроен метод, переносящий все элементы списка:
private void MoveAllItems(ListBox list1, ListBox list2)
{
/*** Все элементы списка list1 ****
**** переносятся в конец списка list2 ****
**** список list1 очищается *************/
list2.Items.AddRange(list1.Items);
list1.Items.Clear();
}
Добавим еще одну функциональную возможность — разрешим переносить элементы из одного списка в другой двойным щелчком кнопки мыши. Для этого зададим обработчики события DoubleClick наших списков:
private void listBox1_DoubleClick(object sender,
System.EventArgs e)
{
/* Обработчик события Doubleclick левого списка
* Выбранный элемент переносится в правый список
* ListBox1 <-> ListBox2******************/
MoveSelectedItems(listBox1, listBox2);
}
private void listBox2_DoubleClick(object sender,
System.EventArgs e)
{
/* Обработчик события Doubleclick правого списка
* Выбранный элемент переносится в левый список
* ListBox1 <-> ListBox2******************/
MoveSelectedItems(listBox2, listBox1);
}
Обработчики вызывают уже рассмотренные нами методы.
На этом закончим рассмотрение функциональности проектируемого образца формы. Но, скажете вы, остался не заданным целый ряд вопросов: непонятно, как происходит заполнение