Как использовать свойство CheckBoxes в ListView, что бы можно было пометить галочкой только одну строку, по аналогии с радио кнопкамиЭтот материал появился, когда мне никак не удавалось выбрать только одну строку, что бы затем, по нажатию кнопки выполнить действия только с одной строкой. Свойство "MultiSelect", установленное в значение равное "false" - не помогало, так как при нажатии кнопки, а дальнейшие действия планировалось выполнить именно по нажатию кнопки, селект со строки сбрасывался. Решение пришло не из интернета, так как там я его не нашел. Пришлось выкручиваться самому. Итак: На форме есть контрол "ListView", его мы инициализируем следующим образом:
lv1.Items.Clear();
lv1.Columns.Clear();
lv1.ForeColor = Color.FromArgb(0, 0, 192);
lv1.Font = button2.Font;
lv1.MultiSelect = false;
lv1.CheckBoxes = true;
lv1.View = View.Details;
lv1.GridLines = true;
lv1.FullRowSelect = true;
lv1.Columns.Add("ID записи", lv1.Width / 10, HorizontalAlignment.Left);
lv1.Columns.Add("ID объекта", lv1.Width / 10, HorizontalAlignment.Left);
lv1.Columns.Add("Объект", 2 * lv1.Width / 5, HorizontalAlignment.Left);
lv1.Columns.Add("Дата", lv1.Width / 10, HorizontalAlignment.Left);
lv1.Columns.Add("Описание", lv1.Width / 10, HorizontalAlignment.Left);
Далее я простым селектом получил данные в DataRow[] (Об этом уже нам известно из раздела 5 книги: Работа с базами данных в Visual Studio .NET).
foreach (DataRow dr in drs)
{
s = dr["nameobj"].ToString().ToUpper();
string[] row = new string[5];
s = dr["datep"].ToString();
if (!string.IsNullOrEmpty(s))
{
s = DateTime.Parse(s).ToString("dd.MM.yyyy");
}
else
{
continue;
}
row[3] = s;
s = dr["id"].ToString();
if (string.IsNullOrEmpty(s)) s = "0";
row[0] = s;
row[1] = dr["idpoint"].ToString();
row[2] = dr["nameobj"].ToString();
s = dr["note"].ToString();
if (string.IsNullOrEmpty(s)) s = "0";
row[4] = s.Replace(",", ".");
var listViewItem = new ListViewItem(row);
lv1.Items.Add(listViewItem);
}
Обратим внимание на два свойства, первое из которых обязательно для многих операций, а второе позволяет отобразить чекбоксы перед каждой строкой: lv1.View = View.Details; lv1.CheckBoxes = true; С этого момента мы можем ставить галочки и сколько угодно, хоть у каждой строки, но нам нужна строка помеченная только одна. Для этого воспользуемся событием ListView - ItemCheck:
private bool fL=false;
private void lv1_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (fL) return;
//Эта блокировка необходима, что бы программа при смене выделенной строки не реагировала на
//сброс галочки в ранее помеченной
fL = true;
//Запоминаем строку, в которой поставили галлочку
int a = e.Index;
//Сбрасываем все галочки
for (int i = 0; i < lv1.Items.Count; i++)
{
lv1.Items[i].Checked = false;
}
//Восстанавливаем галочку в последней выделенной строке
lv1.Items[a].Checked = true;
//С этого момента у меня помечена галочкой только одна строка, при попытке поставить галочку против
//другой строки, ранее установленная галочка сбрасывается.
//С этого момента я могу делать со строкой все, что хочу
//Например, выделяю ее и помещаю содержимое в отделные TextBox (это к пометке галочками строк не относится,
//но служит как пример для чтения данных из ListView)
lv1.Items[a].Selected = true;
if (lv1.SelectedItems.Count > 0)
{
tbId.Text = lv1.SelectedItems[0].Text;
tbIdO.Text = lv1.SelectedItems[0].SubItems[1].Text;
tbO.Text = lv1.SelectedItems[0].SubItems[2].Text;
tbP.Text = lv1.SelectedItems[0].SubItems[4].Text.Replace(",", ".");
}
fL = false;
}
Теперь нам не важно, что при нажатии кнопки на форме пропадет селект на выделенной строке - мы можем работать со строкой, используя свойство "CheckedItems" - у нас одна выделенная строка и мы можем быть в этом уверены!
private void button5_Click(object sender, EventArgs e)
{
if (lv1.Items.Count <= 0) return;
if (lv1.CheckedItems.Count != 1)
{
s = "Не помечена галочкой строка, которую Вы хотите изменить!";
MessageBox.Show(s, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
.....
Молчанов Владислав 27.11.2013г. |