БлогNot. C#: работаем со строками String и списочными компонентами Windows Forms

C#: работаем со строками String и списочными компонентами Windows Forms

I. Основные типы данных .NET для C++ и работа со строками

В среде .NET возможна работа с классическими строками Си (char * или char []) и классом C++ std::string. Но в большинстве случаев в приложениях на C++/CLI или C# применяют встроенный класс .NET System.String.

Есть аналоги и других стандартных типов данных, перечислим основные из них в таблице.

Целочисленные

Byte

8-битовое беззнаковое целое

SByte

8-битовое целое со знаком

Int16

16-битовое целое со знаком

Int32

32-битовое целое со знаком

Int64

64-битовое целое со знаком

UInt16

16-битовое целое без знака

UInt32

32-битовое целое без знака

UInt64

64-битовое целое без знака

Вещественные

Single

число с плавающей точкой с обычной (32 бита) точностью

Double

число с плавающей точкой с двойной (64 бита) точностью

Логические

Boolean

Логическое (булево) значение (true или false)

Другие типы

Char

Unicode (16-битовый) символ

Decimal

Десятичное (128 бит) значение

IntPtr

Целое со знаком, значение которого зависит от соответствующей платформы: 32-битовое значение на 32-битовой платформе и 64-битовое на 64-битовой платформе

UIntPtr

Целое без знака, значение которого зависит от соответствующей платформы: 32-битовое значение на 32-битовой платформе и 64-битовое на 64-битовой платформе

Классы

Object

Корневой класс для иерархии классов

String

Строка Unicode символов постоянной длины

Пример 1. Применяем класс String библиотеки .NET. Код можно выполнить по любому событию.

   String s = "123456";
   String s1 = String.Empty; //s1=""; тоже можно
   s1 = "1234";
   MessageBox.Show(String.Compare(s, s1).ToString(), "Сравнение строк",
    MessageBoxButtons.OK);
   s1 = String.Concat(s, s1);
   MessageBox.Show(s1, "Сцепление строк", MessageBoxButtons.OK);
   s1 = String.Copy(s); //копирование s в s1
   s1 = s1.Insert(2, "***");
   //Вставка "***" со 2-й позиции в s1 (позиции с 0), потом копирование в s
   MessageBox.Show(s1, "Копирование и вставка строк", MessageBoxButtons.OK);

Обратите внимание, что часть методов вызываются как методы класса String (например, Concat), а часть может быть вызвана только для объекта (например, Insert). Обычно методы возвращают либо новую строку, либо позицию в строке, если они предназначены для поиска.

Некоторые другие стандартные функции класса String:

IndexOf("подстрока")

индекс первого вхождения подстроки с 0 или -1 (не найдено)

LastIndexOf("подстрока")

индекс последнего вхождения подстроки

Length

длина строки

PadLeft(N)

помещение числа в N позиций с дополнением пробелами слева

PadRight(N)

помещение числа в N позиций с дополнением пробелами справа

Remove(N,K)

удалить K символов, начиная с позиции N

Replace(S1,S2)

заменить все комбинации символов S1 на S2

Substring(N,K)

с позиции N выделить подстроку в K символов (если K не указано - до конца строки)

В этой таблице не учтены все перегрузки методов, которых значительно больше.

Пример 2. Преобразование типов данных С# в типы .NET

   int i = Int32.Parse("123");
   MessageBox.Show(i.ToString());
   MessageBox.Show(i + ""); //Работают и конструкции такого вида
   float f;
   try {
    f = Single.Parse("123.45");
    //при русской локали - неверный входной формат, FormatException
    //а правильно - разделить запятой
   }
   catch (FormatException ex) {
    MessageBox.Show(ex.Message);
    return;
   }
   MessageBox.Show(f.ToString());
   int j = 1234; 
   String r = j.ToString();
   MessageBox.Show(r); //см. также TryParse 

Пример 3. Преобразование типов данных с помощью методов To*.

   String result = String.Empty;
   double d = 123.45;
   int i = Convert.ToInt32 (d); result += i;
   bool b = Convert.ToBoolean (d); result += " " + b;
   String s = Convert.ToString (d); result += " " + s;
   char c = ' '; 
   try {
    c = Convert.ToChar (d); //Исключение - Double в Char, можно 65
   }
   catch (Exception ex) {
    MessageBox.Show (ex.Message);
   }
   DateTime dt = new DateTime ();
   dt = DateTime.Now;
   result += " " + c + " " + dt.ToString ();
   MessageBox.Show (result, "Результаты", MessageBoxButtons.OK);

II. Списочные компоненты и работа с ними

Базовый списочный класс System::Collections::Generic::List содержит, в основном, шаблоны для организации списков из элементов произвольного типа данных T. Для типовых задач обработки списочных данных обычно применяют описанные ниже компоненты.

Приведём пример на работу с базовым списком строк, код может быть выполнен по любому событию, а результаты обработки списка добавляются в многострочное текстовое поле textBox1.

List <string> list = new List<string>();
list.Add("Первый"); list.Add("Второй"); list.Add("Третий");
textBox1.Clear();
foreach (string item in list) textBox1.AppendText(item + Environment.NewLine);
textBox1.AppendText(String.Format("Список содержит {0}? {1}", 
 list[2], list.Contains(list[2])));
list.Insert(2, "Четвёртый");
list.Remove("Первый");
textBox1.AppendText(Environment.NewLine);
foreach (string item in list) textBox1.AppendText(item + Environment.NewLine);
textBox1.AppendText("Всего: " + list.Count + Environment.NewLine);
textBox1.AppendText("Ёмкость: " + list.Capacity + Environment.NewLine);

Компонента 1. ListBox, базовый список, основные свойства:

  • MultiColumn - разрешает вывод содержимого в несколько колонок;
  • ColumnWidth - ширина колонки в пикселах при многоколоночном списке;
  • SelectionMode - сколько элементов можно выбирать за один раз;
  • SelectedIndex - индекс первого выбранного элемента или -1;
  • SelectedItem - выбранный элемент (обычно строка);
  • Count - количество элементов в списке;
  • Items - изменяемый контейнер с элементами.

Некоторые методы, видно, что доступ к элементам осуществляется через контейнер Items:

  • Items.Add(элемент) - добавить элемент;
  • Items.Insert(позиция,элемент) - вставить элемент в указанную позицию;
  • Items.Clear() - очистить список;
  • Items.Remove("строка") - удалить элемент;
  • Items.RemoveAt(позиция) - удалить элемент по номеру позиции (с нуля).

Пример 4. Код может быть выполнен по любому событию, на форму добавлен компонент listBox1:

   listBox1.Items.Clear ();
   listBox1.Items.Add ("Первый");
   listBox1.Items.Insert (0, "Второй");

А этот код выполним по событию SelectedIndexChanged созданного списка:

   int index = listBox1.SelectedIndex;
   String s = listBox1.Items [index].ToString ();
   MessageBox.Show (s + " в позиции "+index);

Пример 5. Добавив в listBox1 любую достаточно длинную строку, выполним код по нажатию второй кнопки:

   int cnt = listBox1.Items.Count, maxWidth = 0;
   for (int i = 0; i < cnt; i++) {
    int w = (int) listBox1.CreateGraphics ().MeasureString (
     listBox1.Items [i].ToString (), listBox1.Font).Width;
    //узнали ширину элемента в пикселах
    if (w > maxWidth) maxWidth = w;
   }
   MessageBox.Show ("Макс.ширина элемента = " + maxWidth);
   listBox1.ColumnWidth = listBox1.Width = maxWidth + 10;

Пример 6. По нажатию ещё одной кнопки добавим в список строки текста из файла ./data.txt:

   string [] lines;
   try {
    lines = System.IO.File.ReadAllLines ("data.txt");
   }
   catch (Exception ex) {
    textBox1.AppendText (ex.Message);
    MessageBox.Show (ex.Message); return;
   }
   foreach (string line in lines) {
    listBox1.Items.Add (line);
   }

В норме код при первом запуске покажет путь к текущей папке, куда нужно поместить текстовый файл, например, такой:

Файл 'C:\Users\Admin\source\repos\Lab3_1\bin\Debug\data.txt' не найден.

Файл может быть создан в кодировке Юникода UTF-8.

Компонента 2. CheckedListBox - разновидность списка с отметкой элементов чекбоксами.

Проект Lab3_1. Редактируемый телефонный справочник на основе списка

Свойства, установленные компонентам:

  • Form1: FormsBorderStyle=FixedDialog, MaximizeBox=false, Size=640,480. StartPosition=CenterScreen,Text="Справочник"
  • listBox1: Dock = Top, Size = 624;342, Sorted=true, SelectionMode = MultiExtended, Context=contextMenuStrip1 (с пунктами Добавить и Удалить).
  • Остальные элементы размещены на Panel1 (Dock=Bottom, Size = 624;99, BackColor = White):
    • label1, label2 - метки с рисунками (свойство Image, рисунки из папки проекта импортированы в файл ресурсов формы, AutoSize = false, Size=90;90, Text=пусто);
    • maskedTextBox1, maskedTextBox2 - ввод имени и номера,
    • button1, button2 - кнопки "Найти" и "Очистить".

MaskedTextBox - текстовое для ввода данных по шаблону. Для наших полей установим маски (свойство Mask) в значения AAAAAAAAAAAAAAAAAAAA и 999999999999999 соответственно.

Форма примера Lab3_1
Форма примера Lab3_1

Логичней и проще всего, если наше приложение будет автоматически читать считывать файл с данными при загрузке и автоматически сохранять при выходе. Хотелось бы также, чтобы отсутствие файла в текущей папке не смущало приложение и оно могло бы создать его заново. Напишем метод класса формы LoadFromFile для чтения из файла с фиксированным именем data.txt, а метод SaveToFile - для записи. Из кода видно, что мы отделяем номер телефона от фамилии или имени просто символом табуляции \t.

  private void LoadFromFile (String File) { //чтение из файла
   string [] lines;
   listBox1.Items.Clear ();
   try {
    lines = System.IO.File.ReadAllLines (File);
   }
   catch (Exception) {
    System.IO.File.WriteAllText (File, "");
    return;
   }
   foreach (string line in lines) {
    listBox1.Items.Add (line);
   }
   listBox1.SelectedIndex = -1;
  }

  private void SaveToFile (String File) { //запись в файл
   System.IO.StreamWriter SaveFile = new System.IO.StreamWriter (File);
   foreach (var item in listBox1.Items) {
    SaveFile.WriteLine (item.ToString ());
   }
   SaveFile.Close ();
  }

Пункт Добавить контекстного меню, вызываемого нажатием правой кнопки мыши на списке, обработает и поместит в список данные, которые набраны в полях ввода. При этом он гибко позволит как редактировать имеющиеся данные (если в списке есть выбранный элемент), так и создать новый элемент. Повторное добавление одинаковых записей исключим, а действие метода также будем дублировать нажатие клавиши Enter во втором поле ввода (телефон). Заодно сделаем так, чтобы при нажатии Enter в первом поле ввода курсор автоматически переходил во второе, а после Enter во втором поле не только добавлялась или изменялась запись, но и очищались поля ввода с установкой курсора обратно на первое. Это облегчит массовый ввод записей. Лишних сообщений об ошибках создавать не будем, дабы не утомлять пользователя модальными окнами с кнопкой ОК.

Код для события Click пункта меню "Добавить":

   String r = String.Empty;
   String s1 = maskedTextBox1.Text.Trim ();
   String s2 = maskedTextBox2.Text.Trim ();
   if (!( String.IsNullOrEmpty (s1) || String.IsNullOrEmpty (s2) )) {
    r = String.Concat (s1, "\t", s2);
    if (listBox1.SelectedIndex != -1) {
     listBox1.Items [listBox1.SelectedIndex] = r;
     maskedTextBox1.Clear ();
     maskedTextBox2.Clear ();
     listBox1.SelectedIndex = -1;
    }
    else {
     if (listBox1.FindString (r) == -1) //не добавлять, если уже есть в списке
      listBox1.Items.Add (r); 
    }
   }

Код для события KeyDown поля ввода maskedTextBox1:

   //Обработка Enter в первом поле ввода
   if (e.KeyCode == Keys.Enter) maskedTextBox2.Focus ();

Код для события KeyDown поля ввода maskedTextBox2:

   //Обработка Enter во втором поле ввода
   if (e.KeyCode == Keys.Enter) {
    String str = maskedTextBox2.Text.Replace (" ", "");
     //Копия ввода без пробелов
    System.Text.RegularExpressions.Match match =
     System.Text.RegularExpressions.Regex.Match (str, "^[0-9]{4,}$");
    //Требуем не менее 4 цифр
    if (!match.Success) return;
    добавитьToolStripMenuItem_Click (this, e);
    button2_Click (this, e);
   }

Мы дополнительно проверяем, что в поле ввода добавлено не менее 4 цифр с помощью регулярного выражения.

Следует иметь в виду, что для проверки корректности ввода пользователя существует также событие Validating.

Кнопка "Очистить", обработчик события Click которой также здесь вызван, сотрёт содержимое нижних полей ввода и установит курсор в первое из них:

   maskedTextBox1.Clear ();
   maskedTextBox2.Clear ();
   maskedTextBox1.Focus ();

Перед закрытием формы из обработчика события FormClosing будем просто вызывать наш метод сохранения данных в файл:

   SaveToFile ("base.txt");

а на загрузку формы Load - метод чтения из файла:

   LoadFromFile ("base.txt");
   listBox1.SelectedIndex = -1;

Обработчик события Activated формы установит фокус в первое поле ввода:

   maskedTextBox1.Focus ();

Пункт меню "Удалить" сделает свою работу, если он вызван при каком-то выбранном в списке элементе:

   if (listBox1.SelectedIndex != -1) {
    listBox1.Items.Remove (listBox1.SelectedItem);
    if (listBox1.Items.Count == 0) listBox1.SelectedIndex = -1;
   }

Обычный клик левой кнопкой мыши по элементу списка (событие Click для него) разберёт хранящуюся там строку на части "имя" и "номер" и скопирует их в нижние поля ввода для редактирования.

   if (listBox1.SelectedIndex < 0) return;
   String s = listBox1.Items [listBox1.SelectedIndex].ToString ();
   int i = s.IndexOf ("\t");
   if (i < 0) return;
   String s1 = s.Substring (0, i);
   maskedTextBox1.Text = s1;
   maskedTextBox2.Text = s.Substring (i + 1);

Списочные компоненты не предусматривают редактирование данных "на месте", то есть, непосредственно в списке, эта задача либо решается с помощью табличных компонент, либо по нужному событию программно создаётся текстовое поле, выводимое поверх списка в рассчитанных координатах на форме.

Код кнопки Найти выглядит чуть сложнее, но решит, в сущности, простую задачу - пометит выделенными все элементы списка, хотя бы частично совпадающие с введёнными в первое или второе текстовое поле строками.

   String a;
   String s1 = maskedTextBox1.Text.Trim ();
   String s2 = maskedTextBox2.Text.Trim ();
   int n = listBox1.Items.Count;
   for (int i = 0; i < n; i++) listBox1.SetSelected (i, false); 
    //снять все выделения в списке
   for (int i = 0; i < n; i++) {
    a = listBox1.Items [i].ToString ();
    int p = a.IndexOf ("\t");
    String phone, name;
    if (p > -1) {
     name = a.Substring (0, p);
     phone = a.Substring (p);
     if (String.IsNullOrEmpty (s1) == false && name.IndexOf (s1) > -1 ||
         String.IsNullOrEmpty (s2) == false && phone.IndexOf (s2) > -1) {
      listBox1.SetSelected (i, true);
     }
    }
   }

Наше приложение готово, конечно, оно далеко не совершенно, но основой для вашей дальнейшей работы служить может.

 Скачать пример Lab3_1 в архиве .zip с проектом C#, Visual Studio 2019 (19 Кб)

Компонента 3. ComboBox - комбинация редактируемого поля и списка.

Вот некоторые полезные свойства:

  • DropDownStyle - стиль вывода: Simple - редактирование, кнопка раскрытия списка спрятана, DropDown - выпадающий с редактированием, DropDownList - выпадающий без редактирования;
  • Text - есть для доступа к редактируемой строке
  • DropDownWidth, DropDownHeight - ширина и высота выпадающего списка
  • FlatStyle - стиль окна редактирования: Popup - всплывающее, System - смена цвета
  • FormatString - форматирование даты, чисел, валют и т.п.
  • AutoCompleteMode - автозавершение.

Пример 7. В обработчике некоторого события загрузили в ComboBox список логических дисков:

   comboBox1.DataSource = System.Environment.GetLogicalDrives ();

Пример 8. В обработчике события заполнили список из массива строк.

   String [] lines = { "P1", "P2", "P3" };
   for (int i = 0; i < lines.Length; i++) comboBox1.Items.Add (lines[i]);
   comboBox1.SelectedIndex = 0;  //или comboBox1.SelectedItem = lines[0];

Пример 9. Разобрали строку списка по формату и показали её.

   comboBox1.Items.Add ("123,4567");
   String str = String.Format ("S={0,-12:N2}", comboBox1.Items[0]);
   /* { index[,длина][ :формат] }
   Квадратные скобки обозначают необязательные элементы.
   +длина выравнивание по правому краю, -длина по центру, нету - по левому
   формат N2 - 2 знака после запятой */
   MessageBox.Show (str);

Приложение Lab3_2. Реализовать отсортированный по алфавиту список имён с поддержкой операций добавления и удаления элементов, сохранением списка строк в файл и загрузкой его из файла. Допустимые символы в именах – буквы и цифры. Задачу можно решать как на основе списочных, так и табличных компонент. Поскольку требуется сортировка данных, удобнее решать на основе какого-либо списка, имеющего встроенное свойство Sorted. Форма будет иметь следующий вид:

Форма приложения Lab3_2
Форма приложения Lab3_2

Справа расположена panel1 со свойством Dock = Right, на ней 4 кнопки button1, …, button4 для выполнения предусмотренных задачей действий. Слева – список comboBox1 со свойством Dock = Fill.

По загрузке формы в обработчике события Load настроим список для нашей задачи:

   comboBox1.Sorted = true; //список будет сортироваться
   comboBox1.DropDownStyle = ComboBoxStyle.Simple; //развёрнутый вид

Кнопка "+" будет добавлять запись, если такой же записи ещё нет в списке:

   String r = comboBox1.Text;
   if (comboBox1.FindString (r) == -1) comboBox1.Items.Add (r);

Кнопка "-" будет удалять выбранный в списке элемент, если таковой есть:

   if (comboBox1.SelectedIndex != -1) 
    comboBox1.Items.Remove (comboBox1.SelectedItem);

Кнопка "Load" отвечает за загрузку элементов списка из файла, для простоты вновь используем файл с фиксированным именем data.txt, располагающийся в текущей папке. Однако чтобы можно было закрыть дескриптор файла после чтения данных, применим поточный класс StreamReader:

   comboBox1.Items.Clear ();
   try {
    System.IO.StreamReader file = new System.IO.StreamReader ("data.txt");
    String line;
    while ((line = file.ReadLine ()) != null) comboBox1.Items.Add (line);
    file.Close ();
   }
   catch (Exception) {
    MessageBox.Show("Не могу открыть data.txt");
   }

Кнопка "Save" выполнит аналогичную работу по сохранению файла с использованием поточного класса StreamWriter:

   try {
    System.IO.StreamWriter file = new System.IO.StreamWriter ("data.txt");
    for (int i = 0; i < comboBox1.Items.Count; i++) {
     file.WriteLine (comboBox1.Items [i].ToString ());
    }
    file.Close ();
   }
   catch (Exception) {
    MessageBox.Show ("Не могу записать data.txt");
   }

Осталось обеспечить ввод только разрешённых символов (букв и цифр), для этого достаточно добавить обработчик события KeyPress для списка comboBox1:

   char c = e.KeyChar;
   if (Char.IsLetterOrDigit (c) || c == (char) Keys.Back 
    || c == (char) Keys.Enter)
    return;
   else e.Handled = true;

 Скачать пример Lab3_2 в архиве .zip с проектом C#, Visual Studio 2019 (11 Кб)

Компонента 4. "Список-коллекция" ListView, позволяющий отображать данные в одном из пяти стандартных для современных графических операционных систем представлений. Вот некоторые полезные свойства этой компоненты:

  • View - вид списка (из 5 стандартных);
  • Columns - заголовки колонок для View = Details или Tile;
  • Groups - позволяет группировать элементы при View != List;
  • HeaderStyle - стиль заголовка колонки при View = Details;
  • Items - контейнер для элементов;
  • LargeImageList, SmallImageList - иконки (контейнеры ImageList) для основных режимов просмотра списка;
  • SelectedItems - контейнер для выбранных элементов;
  • MultiSelect - разрешает множественный выбор;
  • CheckBoxes - разрешает выводить окна контроля рядом с элементами при View!=Tile;
  • CheckedItems - свойство для помеченных элементов, а событие пометки элемента можно обработать в ItemCheck;
  • CheckedIndices - индексы помеченных элементов;
  • StateImageList - позволяет задать ImageList вместо чекбоксов контроля
  • Activation - выбираем элемент через OneClick или TwoClick;
  • HotTracking - позволяет показывать элемент как гиперссылку;
  • GridLines - показывает разделительные линии между элементами;
  • LabelEdit - можно ли редактировать текст элемента.

Приложение Lab3_3. Управляем представлениями списка ListView.

Добавим на пустую форму Windows Forms список ListView, выровняем его по форме (свойство Dock = Fill).

На форму также добавлен список иконок ImageList с 3 картинками, соответствующими типам объектов списка. Типы эти могут быть любыми, например, см. показанные на картинке. Подготовим 3 квадратных картинки с соответствующими типам изображениями и добавим их в ImageList в указанном порядке.

Также понадобится стандартное меню MenuStrip, предусмотрим в нём разделы Список и Вид. В меню Список содержится подменю Добавить с элементами, соответствующими 3 типам объектов, а также пункты Удалить и Выход. Меню Вид предназначено для переключения между 5 стандартными видами списка (см. свойство View). Соответственно, оно содержит пункты Большие иконки, Малые иконки, Детали, Список, Мозаика:

Меню приложения Lab3_1
Меню приложения Lab3_1

Если выделить список в конструкторе формы и нажать треугольник в правом верхнем углу, мы увидим ссылки на все его основные сущности:

Быстрое редактирование основных свойств списка ListView
Быстрое редактирование основных свойств списка ListView

Во-первых, у списка имеются элементы типа данных ListViewItem. В редакторе коллекции можно добавить предустановленные элементы и назначить им свойства. Добавим один элемент, допустим, HedgeHog_Admin (свойство Text).

Во-вторых, у списка может быть несколько столбцов с заголовками (ColumnHeader). Они видны в режиме просмотра Детали и, возможно, Мозаика. По умолчанию есть один столбец, отображающий свойство Text элементов, можно создать дополнительные. Добавим в редакторе коллекции "Столбцы" Элемент (Name=element, Text=Элемент) и Дата (Name=dateTime, Text=Дата), назначим им нужную ширину Width в пикселах, например, в 120 и 100 соответственно.

В-третьих, список позволяет создать несколько групп (свойство Groups), которые будут логически объединять элементы по нужному программисту критерию. Создадим 3 группы с заголовками (свойство Header), соответствующими 3 нашим типам объектов, то есть "Ёжики", "Крысы" и "Тараканы".

Здесь же можно поставить наш imageList1 на свойства LargeImage и SmallImage списка listView1.

Теперь, вызвав редактор коллекции ListViewItem ("Изменить элементы") щёлкнем на многоточии справа от свойства SubItems и в редакторе коллекции ListViewSubItem добавим подэлемент со свойствами Name = dateTime, Text = 01.01.1970 00:00:00 (чтобы у предустановленного ёжика-админа тоже была дата создания, соответствующая началу эпохи Unix) Также назначим предустановленному элементу Group=Ёжики, раз группы уже созданы.

Для добавления элемента в список создадим в классе формы Form1.cs метод AddItem:

  private void AddItem (String text, int icon) {
   ListViewItem lvi = new ListViewItem ();
   lvi.Text = text;
   lvi.ImageIndex = icon; //Создать элемент, назначить текст и иконку
   ListViewItem.ListViewSubItem lvsi = new ListViewItem.ListViewSubItem ();
   lvsi.Text = DateTime.Now.ToString ();
   lvi.SubItems.Add (lvsi); //Добавили подэлемент с текущей датой/временем
   lvi.Group = listView1.Groups [icon]; 
    //Добавили эл-т в группу, соотв.-ю номеру иконки
   listView1.Items.Add (lvi); //Положили элемент в контейнер
  }

По пунктам подменю "Добавить" запрограммируем создание объекта каждого из 3 видов, вот код для первого вида:

   int cnt = listView1.Items.Count + 1;
   AddItem ("HedgeHog_" + Convert.ToString (cnt), 0);

Аналогично для остальных 2 пунктов, назначив строки "Rat_" и "Beetle_" вместо "HedgeHog_" и номера 1, 2 вместо 0.

По пункту меню Удалить просмотрим коллекцию выделенных элементов SelectedItems и удалим её элементы из списка:

   while (listView1.SelectedItems.Count > 0) {
    ListViewItem item = listView1.SelectedItems [0];
    listView1.Items.Remove (item);
   }

Выделить несколько элементов списка можно при зажатой клавише Ctrl, это в него встроено.

Пункты меню Вид переключают стандартные представления объектов списка, например, для пункта "Большие иконки" код будет таким:

   listView1.View = View.LargeIcon;

Для остальных пунктов меню Вид просто поставьте SmallIcon, Details, List, Tile вместо LargeIcon. Лучше, конечно, если эти 5 пунктов будут взаимозависимы и на выбранном пункте будет ставиться свойство Checked = True, а на остальных False, для простоты пока этого делать не будем.

Осталось запрограммировать пункт Выход:

   Application.Exit ();

и пример готов.

Разумеется, на его основе можно сделать гораздо больше, если понимать, что ListView - готовый шаблон для стандартных представлений любых списочных данных, скажем, предусмотрев типы объектов "Диск", "Папка" и "Файл" на его основе можно написать Проводник.

Для сортировки всего списка ListView по первому столбцу достаточно поставить его свойство Sorting = Ascending (или Descending, если нужно по убыванию), а для нескольких столбцов при виде "Детали" сортировка по клику на заголовке столбца от этого не появится, её нужно программировать отдельно, в нашем случае подойдёт обработчик события ColumnClick списка, готовый пример для сортировки есть вот тут в msdn, можно его приспособить для нашего случая.

 Скачать пример Lab3_3 в архиве .zip с проектом C#, Visual Studio 2019 (16 Кб)

В качестве задания по списочным компонентам подойдёт, например, такое.

Согласно варианту задания, выбрать необходимые поля списка и реализовать приложение на основе списочных компонент. Список должен содержать не менее 2 полей, например, "Фамилия" и "Номер телефона" или "Термин" и "Описание".

Минимальные функции приложения:

  • Добавление, редактирование, удаление элементов;
  • Проверка корректности данных;
  • Сортировка списка по полю или полям, для которых это имеет смысл;
  • Сохранение данных в файле и загрузка из файла;
  • Проверка того, сохранены ли данные при закрытии приложения.

Защита работы может предполагать добавление в приложение дополнительных функций.

Варианты задания:

1. Студенты

2. Сотрудники организации

3. Имена и фамилии для генерации их комбинаций

4. Товары и цены на них

5. Записная книжка расходов

6. Записная книжка встреч

7. Страны мира или регионы страны

8. Города или населённые пункты

9. Операторы языка программирования

10. Теги HTML (или другого формата разметки)

11. Названия и RGB-коды цветов

12. Коллекция ссылок на сайты

13. Перечень терминов и их описаний

14. Отрезки на плоскости

15. Химические элементы

16. Коллекция книг (или иных объектов)

17. Алгоритмические задачи (с ответом-числом)

18. Рейтинги в какой-либо сфере деятельности

19. Записная книжка контактов

20. Календарь погоды

27.02.2023, 19:37 [973 просмотра]


теги: программирование учебное список c#

К этой статье пока нет комментариев, Ваш будет первым