Назад Вперед Зміст


Елемент керування DataGridView

Елемент керування DataGridView надає потужний та гнучкий спосіб відображення даних у табличному форматі. Він може використовуватись для відображення невеликих обсягів даних лише для перегляду, або масштабуватись для редагування великих наборів даних.

Для реалізації спеціальної поведінки в програмах, елемент DataGridView можна розширити різними способами. Наприклад, можна програмно задати власні алгоритми сортування, створити спеціальні типи комірок. Зовнішній вигляд легко налаштовується через властивості.

Дані можуть надходити з:

  1. бази даних
  2. колекцій
  3. внутрішніх змінних
  4. масивів чи інших об'єктів програми
  5. також DataGridView може працювати без прив'язаного джерела даних

Типи даних у комірках DataGridView:

  1. dataGridViewButtonColumn - комірки у вигляді кнопок
  2. dataGridViewCheckBoxColumn - комірки-прапорці
  3. dataGridViewComboBoxColumn - комірки-випадаючі списки
  4. dataGridViewImageColumn - комірки-зображення
  5. dataGridViewLinkColumn - комірки-посилання
  6. dataGridViewTextBoxColumn - стандартні текстові комірки

Задання розмірів DataGridView1

Висота - 200 пікселів. Ширина - 350 пікселів

dataGridView1.Width = 350;
dataGridView1.Height = 200;

Додавання стовпця програмним шляхом

Стовпці в DataGridView організовані у вигляді колекції Columns типу DataGridViewColumnCollection.

Метод Add має 2 варіанти реалізації:

  1. int DataGridViewColumnCollection.Add(DataGridViewColumn dataGridViewColumn);
  2. int DataGridViewColumnCollection.Add(string ColumnName, string HeaderText);

Приклад додавання стовпців:


private void button1_Click(object sender, EventArgs e)
{
    dataGridView1.Columns.Add("column-1", "Header column - 1");
    dataGridView1.Columns.Add("column-2", "Header column - 2");
}

Додавання рядків

Рядки можна додавати двома способами:

  1. шляхом безпосереднього введення з клавіатури
  2. програмно

private void button3_Click(object sender, EventArgs e)
{
    if (dataGridView1.Columns.Count <= 0)
    {
        label1.Text = "Рядки не додано";
        return;
    }
    dataGridView1.Rows.Add("Ivanov I.I.", 25, "New York");
    dataGridView1.Rows.Add("Petrenko P.P.", 38, "Moscow");
    label1.Text = "Рядки додано";
}

Приклад використання DataGridView

Розмістимо на формі компонент DataGridView, створимо 4 стовпці - назва точки, координати x, y, z. Потім введемо кілька рядків.

Щоб обчислити площу трикутника, побудованого за трьома точками, введеними в DataGridView, потрібно виконати наступні кроки:

  1. Вибрати три точки з таблиці: Можна використовувати механізм виділення рядків у DataGridView. Наприклад, можна виділити три рядки та отримати координати точок.
      У DataGridView рядки можна вибирати різними способами:
    • 1. Виділення рядків мишею: За замовчуванням користувач може клацнути на рядок, щоб виділити його. Можна утримувати клавішу Ctrl та клацати на інші рядки для виділення кількох рядків одночасно.
    • 2. Програмне виділення рядків: Для програмного виділення можна використовувати властивість Selected об'єкта DataGridViewRow. Приклад коду:
      // Приклад програмного виділення перших трьох рядків
      dataGridView.Rows[0].Selected = true; dataGridView.Rows[1].Selected = true; dataGridView.Rows[2].Selected = true;
    • Можна налаштувати режим виділення:
      dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
      dataGridView.MultiSelect = true; // Дозволяє виділяти кілька рядків
      SelectionMode визначає, що саме можна виділяти у DataGridView.
      FullRowSelect дозволяє виділяти цілі рядки. MultiSelect дозволяє користувачу виділяти кілька рядків одночасно.
  2. Отримати координати точок:

    Отримати координати x, y, z з виділених рядків.

    
    if (dataGridView.SelectedRows.Count == 3) 
    { 
        foreach (DataGridViewRow row in dataGridView.SelectedRows) 
        { 
            // Отримати значення стовпця з координатою X 
            double x = Convert.ToDouble(row.Cells["X"].Value); 
            // Аналогічно обробити координати Y та Z 
        } 
    }
  • Обчислити площу трикутника:

    Використати формулу для площі трикутника у просторі, засновану на векторному добутку.

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

    У тривимірному просторі це означає, що векторний добуток векторів, утворених цими точками, не дорівнює нулю.

    Доки не введено три точки, кнопка обчислення площі трикутника недоступна.

    Щоб розблокувати кнопку після введення трьох рядків у DataGridView, потрібно перевіряти кількість рядків.

    Також слід враховувати, що рядки можуть бути додані або видалені.

    Ось як це можна зробити:

    1. Обробка подій RowsAdded та RowsRemoved:

      Ці події викликаються при додаванні або видаленні рядків.

    2. Перевірка кількості рядків та розблокування кнопки:

      ОбробникиRowsAdded та RowsRemoved відстежують зміни в DataGridView та викликають метод CheckRowCount.

      CheckRowCount: Метод перевіряє кількість заповнених рядків (виключаючи порожні рядки та рядок для введення нових даних).

      Якщо заповнених рядків 3 або більше, кнопка CalcArea розблоковується, інакше залишається заблокованою.

      Переконайтеся, що ви підписані на ці події:

      this.dataGridView1.RowsAdded += new DataGridViewRowsAddedEventHandler(this.dataGridView1_RowsAdded);
       this.dataGridView1.RowsRemoved += new DataGridViewRowsRemovedEventHandler(this.dataGridView1_RowsRemoved);

      Цей код автоматично розблокує кнопку, коли в таблиці буде три або більше заповнених рядків, і заблокує її, якщо рядків стане менше.

  • Клас форми

    
    namespace DataGrid1
    {
        public struct Point3D
        {
            public double X; 
            public double Y; 
            public double Z;
        }
    
        public partial class Form1 Form 
        {
            public Form1() { 
    		// Ініціалізація компонентів
    		InitializeComponent(); }
    
            private void Form1_Load(object sender,EventArgs e) { }
    
            private void  dataGridView1_RowsAdded(object  sender, DataGridViewRowsAddedEventArgs e)
            {
                // Перевірити кількість рядків при додаванні
                CheckRowCount(); 
            }
    
           private void  dataGridView1_RowsRemoved(object sender,DataGridViewRowsRemovedEventArgs e)
            {
                // Перевірити кількість рядків при видаленні 
                CheckRowCount(); 
            }
    
           private void  CheckRowCount()
            {
                // Рахуємо кількість заповнених рядків 
               int filledRowCount = dataGridView1.Rows
                    .Cast<DataGridViewRow>()
                    .Count(row => !row.IsNewRow && row.Cells.Cast<DataGridViewCell>()
                        .All(cell => cell.Value != null && cell.Value.ToString() != string.Empty));
    
                // Якщо заповнено 3 або більше рядків, активуємо кнопку
                if(filledRowCount >= 3)
                {
                    this.CalcArea.Enabled = true;
                }
                else
                {
                    this.CalcArea.Enabled = false;
                }
            }
        }
    }

    button2_Click - додає новий рядок до таблиці dataGridView1 з даними з текстових полів

    button4_Click - закриває додаток

    
    private void  button2_Click(object  sender,EventArgs e)  
    {  
       // Додати рядки до таблиці
       if (dataGridView1.Columns.Count <= 0)  
        {  
            MessageBox.Show("Стовпці не додані до таблиці");  
            return;  
        }  
        dataGridView1.Rows.Add(textBox6.Text, textBox3.Text, textBox4.Text, textBox5.Text);  
        MessageBox.Show("Рядки успішно додані");  
    }  
    private  void  button4_Click(object  sender, EventArgs e)  
    {  
         // Закрити додаток
        Application.Exit();  
    }  
      
    
    private void button3_Click(object sender, EventArgs e)
    {
        // Деактивувати кнопку додавання точок 
        this.addPoint.Enabled = false;
        
        // Створити об'єкт для розрахунку площі трикутника
    	TriangleAreaCalculator myTriangle = newTriangleAreaCalculator();
        
        // Обчислити площу за обраними точками
        double S = myTriangle.SelectedPoints(this.dataGridView1);
        
        // Вивести результат або повідомлення про помилку
        if (S > 0) 
        {
            label9.Text = S.ToString();
        }
        else 
        {
            label9.Text = "Неможливо побудувати трикутник за обраними точками.";
        }
    }
     

    Контроль введення координат точок у текстові поля

    
    private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
    {
        char ch = e.KeyChar;
        TextBox textBox = sender as TextBox;
        string tx = textBox.Text;
        // Дозволити керуючі символи (наприклад, Backspace)
        if (char.IsControl(e.KeyChar)) { return; }
        // Перевірка на наявність коми
        int n = tx.IndexOf(",");
        // Перевірка на наявність знаку мінус
        int mn = tx.IndexOf("-");
        // Дозволити цифри
        if (Char.IsDigit(ch)) { return; }
        // Дозволити кому, якщо її ще немає в тексті
        if (ch == ',' && n == -1) { return; }
        // Дозволити знак мінус, якщо він на початку тексту і ще не доданий
        if (ch == '-' && textBox.SelectionStart == 0 && mn == -1) { return; }
        // Якщо символ не відповідає правилам, заборонити його введення
        e.Handled = true;
    }
    

    Клас Трикутник

    
    internal class TriangleAreaCalculator
        {
            public double SelectedPoints(DataGridView dataGridView)
            {
                if (dataGridView.SelectedRows.Count != 3)
                {
                    MessageBox.Show("Оберіть рівно три рядки.");
                    return -1;
                }
                var points = dataGridView.SelectedRows.OfType().Select(row => new Point3D
                {
                    X = Convert.ToDouble(row.Cells["X"].Value),
                    Y = Convert.ToDouble(row.Cells["Y"].Value),
                    Z = Convert.ToDouble(row.Cells["Z"].Value)
                }).ToArray();
                return CalculateArea(points[0], points[1], points[2]);
            }
    
            private static double CalculateArea(Point3D p1, Point3D p2, Point3D p3)
            {
                // Вектор AB
                var AB = new Point3D
                {
                    X = p2.X - p1.X,
                    Y = p2.Y - p1.Y,
                    Z = p2.Z - p1.Z
                };
                
                // Вектор AC
                var AC = new Point3D
                {
                    X = p3.X - p1.X,
                    Y = p3.Y - p1.Y,
                    Z = p3.Z - p1.Z
                };
    
                // Векторний добуток AB × AC
                var crossProduct = new Point3D
                {
                    X = AB.Y * AC.Z - AB.Z * AC.Y,
                    Y = AB.Z * AC.X - AB.X * AC.Z,
                    Z = AB.X * AC.Y - AB.Y * AC.X
                };
    
                // Довжина вектора добутку (площа паралелограма)
                double area = Math.Sqrt(crossProduct.X * crossProduct.X + 
                                       crossProduct.Y * crossProduct.Y + 
                                       crossProduct.Z * crossProduct.Z);
    
                // Площа трикутника - половина площі паралелограма
                return area / 2;
            }
        }
    }

    Функція CanFormTriangle: Перевіряє, чи можна побудувати трикутник за трьома точками. Якщо векторний добуток векторів не дорівнює нулю, то трикутник можна побудувати.

    Метод CheckIfTriangleCanBeFormed:

    Отримує вибрані рядки та витягує координати точок.

    Select — це метод LINQ, який виконує проекцію елементів колекції. Він застосовує вказаний вираз до кожного елементу колекції та повертає новий об'єкт для кожного елементу.

    Перевіряє, чи можна побудувати трикутник.

    Якщо трикутник можна побудувати, то обчислюється його площа.

    Векторний добуток для знаходження площі трикутника у просторі обчислюється за формулою:

    0.5 * Math.Sqrt(crossProduct.X * crossProduct.X + crossProduct.Y * crossProduct.Y + crossProduct.Z * crossProduct.Z);

    Якщо ні, виводиться повідомлення, що точки лежать на одній прямій.

    Приклад. Сортування Посилання:Повторити сортування.

    Аналіз часу роботи алгоритмів сортування

    Швидке сортування Хоара

    Розглянемо алгоритм швидкого сортування - це досить популярний алгоритм, який використовується у стандартній функції sort мови C++.

      Суть алгоритму:
    1. З масиву вибирається опорний елемент (зазвичай середній, але це не принципово)
    2. Усі елементи, менші або рівні йому, переміщуються у ліву частину масиву, а більші або рівні - у праву
    3. Для кожної частини рекурсивно викликається функція сортування

    Напишемо рекурсивну функцію для його реалізації: public void QuickSort(){ QSort(0, n - 1);}

    QuickSort викликає рекурсивну процедуру QSort, передаючи їй межі масиву, що сортується. Сортуваний масив arr задається відповідним полем класу.

    Алгоритм поділу області сортування на частини (Qsort())

    Значення середнього елемента зберігаємо у змінній item, вводимо два поточні індекси ind1 та ind2, які спочатку вказують на ліву та праву межу.

    Індекс ind1 переміщаємо вправо (збільшуємо), доки не знайдемо елемент більший або рівний опорному.

    Індекс ind2 переміщаємо вліво (зменшуємо), доки не знайдемо елемент менший або рівний опорному.

    Потім елементи, на яких ми зупинилися, міняємо місцями, а індекси ind1 та ind2 продовжуємо змінювати (ind1 збільшуємо, ind2 зменшуємо).

    Процес продовжується, доки виконується умова ind1 ≤ ind2. Як тільки ind1 стане більшим за ind2, процес припиняється.

    Після поділу масиву на дві частини (ліва - елементи ≤ item, права - елементи ≥ item), для кожної з цих частин рекурсивно викликаємо функцію QSort().

    
    // Викликає рекурсивну процедуру QSort,
    // передаючи їй межі масиву, що сортується.
    // Масив для сортування arr задається
    // відповідним полем класу.
    //</summary>
    public void QuickSort()
    {
        QSort(0, n - 1);
    }
    
    
    // Невелика за розміром процедура містить три
    // вкладені цикли while, два оператори if та рекурсивні
    // виклики. Для таких процедур задання інваріантів та
    // доведення коректності полегшує налагодження.
    // Передумова: (start <= finish)
    // Результат: масив arr відсортований за зростанням
    // Рекурсивна реалізація алгоритму швидкого сортування (QuickSort)
    //<param name="start">Початковий індекс ділянки масиву для сортування</param>
    // <param name="finish">Кінцевий індекс ділянки масиву для сортування</param>
    void QSort(int start, int finish)
    {
        // Якщо ділянка масиву містить більше одного елемента
        if (start != finish)
        {
            // Вибираємо випадковий опорний елемент
            int ind = rnd.Next(start, finish);
            int item = arr[ind];
            int ind1 = start, ind2 = finish;
            int temp;
    
            // Розділення масиву на дві частини
            while (ind1 <= ind2)
            {
                // Знаходимо елемент, більший або рівний опорному
                while ((ind1 <= ind2) && (arr[ind1] < item)) ind1++;
                
                // Знаходимо елемент, менший опорного
                while ((ind1 <= ind2) && (arr[ind2] >= item)) ind2--;
    
                // Обмін знайдених елементів
                if (ind1 < ind2)
                {
                    temp = arr[ind1]; 
                    arr[ind1] = arr[ind2];
                    arr[ind2] = temp;
                    ind1++;
                    ind2--;
                }
            }
    
            // Обробка особливого випадку, коли всі елементи менші опорного
            if (ind1 == start)
            {
                temp = arr[start]; 
                arr[start] = item;
                arr[ind] = temp;
                QSort(start + 1, finish);
            }
            else 
            {
                // Рекурсивне сортування лівої та правої частин
                QSort(start, ind1 - 1);
                QSort(ind2 + 1, finish);
            }
        }
    }
     

    Практична робота

    Створити проект, який розбирали на уроці. Швидке сортування Хоара показано нижче, самостійно написати та підключити сортування бульбашкою та вибором.

    Починаємо зі створення масиву.

    Додайте одразу клас Form1 та клас SortingArrs, у якому вже є коди швидкого сортування.

    
    public partial class Form1 : Form
    {
        SortingArrs A;  // Об'єкт для сортування масивів
        int m, n = 1;   // Розміри масиву
    
        public Form1()
        {
            InitializeComponent();
        }
    
        private void размерМассиваToolStripMenuItem_Click(object sender, EventArgs e)
    {
        this.textBoxArraySize.Enabled = true;
        if (string.IsNullOrWhiteSpace(textBoxArraySize.Text))
        {
            MessageBox.Show("Поле не должно быть пустым!");
            return;
        }
             m = int.Parse(this.textBoxArraySize.Text);
    }
    
        private void AddColumns(int n, DataGridView dgw)
        {
            DataGridViewColumn column;
            for (int i = 0; i < n; i++)
            {
                column = new DataGridViewColumn();
                column.HeaderText = "Стовпець" + i.ToString();
                column.Name = "Column" + i.ToString();
                dgw.Columns.Add(column.Name, column.HeaderText);
            }
        }
    }
    // Додає рядки до таблиці DataGridView
    private void AddRows(int m, DataGridView dgw)
    {
        for (int i = 0; i < m; i++)
        {
            dgw.Rows.Add();
            dgw.Rows[i].HeaderCell.Value = i.ToString();
        }
    }
    private void создатьМассивToolStripMenuItem_Click(object sender, EventArgs e)
      {
          m = int.Parse(this.textBoxArraySize.Text);
          A = new SortingArrs(m);//Создание массива
          A.FillRndNumbers();
          int k; k = this.dataGridView1.ColumnCount;   //Чистка таблицы
          if (k != 0)
              for (int i = 0; i < k; i++)
                  this.dataGridView1.Columns.RemoveAt(0);
          n = 1;
          AddColumns(n, this.dataGridView1);
          AddRows(m, this.dataGridView1);
      }
    // Обробник події заповнення масиву випадковими числами
    
    private void заполнитьМассивToolStripMenuItem_Click(object sender, EventArgs e)
    {
        this.A.FillRndNumbers();
        for (int i = 0; i < m; i++)
        { dataGridView1.Rows[i].Cells[0].Value = this.A.arr[i].ToString(); }
    
    }
    // Обробник події закриття програми
    private void выходToolStripMenuItem_Click(object sender, EventArgs e)
            {
                Application.Exit();
            }
    // Обробник події контролю вводу
     private void textBoxArraySize_KeyPress(object sender, KeyPressEventArgs e)
            {
                // Разрешить клавиши управления: Backspace, Delete, стрелки
                if (char.IsControl(e.KeyChar))
                    return;
                // Разрешить только цифры
                if (!char.IsDigit(e.KeyChar))
                    e.Handled = true;
            }
    
    }
    // Обробники події для сортування масиву обраним методом
    private void быстраяСортировкаToolStripMenuItem_Click(object sender, EventArgs e)
    {
        A.QuickSort(); this.label3.Text += "QuickSort";
        textBox1.Text = A.AnalyseTimeQuickSort().Time.ToString();
        this.textBoxSwapCount.Text=A.AnalyseTimeQuickSort().CountSwap.ToString();
        for (int i = 0; i< m; i++)
        {
            dataGridView1.Rows[i].Cells[0].Value = this.A.arr[i].ToString();
        }
    }
    
    private void сортировкаСлияниемToolStripMenuItem_Click(object sender, EventArgs e)
    {
        A.SortMerge(); this.label3.Text += "MergeSort";
        textBox1.Text = A.AnalyseTimeMergeSort().Time.ToString();
        this.textBoxSwapCount.Text = A.AnalyseTimeMergeSort().CountSwap.ToString();
        for (int i = 0; i < m; i++)
        {
            dataGridView1.Rows[i].Cells[0].Value = this.A.arr[i].ToString();
        }
    }
    
    private void пирамидальнаяСортировкаToolStripMenuItem_Click(object sender, EventArgs e)
    {
        A.PyramidSort(); this.label3.Text += "PyramidSort";
        textBox1.Text = A.AnalyseTimeHeapSort().Time.ToString();
        this.textBoxSwapCount.Text = A.AnalyseTimeHeapSort().CountSwap.ToString();
        for (int i = 0; i < m; i++)
        {
            dataGridView1.Rows[i].Cells[0].Value = this.A.arr[i].ToString();
        }
    }
    // Обробник події оновлення даних - повертає масив до початкового стану
    private void перезагрузитьИсходныToolStripMenuItem_Click(object sender, EventArgs e)
    {
        label3.Text = "Время в миллисекундах ";
        for (int i = 0; i < m; i++)
        {
            dataGridView1.Rows[i].Cells[0].Value = this.A.copyarr[i].ToString();
            A.arr[i] = A.copyarr[i];
        }
    }
     

    У класі SortingArrs, де вже є код швидкого сортування, додайте решту алгоритмів.

    За цим посиланням можна скопіювати код проекту сортувань.Перейти на сторінку з кодом.

    // Вимірює час виконання сортування
    private long HowLong(SortMethod sort)
    {
        Stopwatch stopwatch = new Stopwatch(); // Створюємо таймер
        stopwatch.Start();                    // Запускаємо вимірювання
        sort();                               // Виконуємо сортування
        stopwatch.Stop();                     // Зупиняємо таймер
        return stopwatch.ElapsedMilliseconds; // Повертаємо витрачений час
    }
    // Кількість операцій обміну  
        private long HowCountSwap(SortMethod sort)
        {
            // Восстанавливаем исходный массив перед каждой сортировкой
            Array.Copy(copyarr, arr, n);
            swapCount = 0;
            sort();
            return swapCount;
        }
     public Analyse AnalyseSort(SortMethod method)
            {
                // Восстанавливаем исходный массив перед анализом
                Array.Copy(copyarr, arr, n);
                long time = HowLong(method);
    
                // Восстанавливаем исходный массив перед подсчетом перестановок
                Array.Copy(copyarr, arr, n);
                long countSwap = HowCountSwap(method);
    
                return new Analyse(time, countSwap);
            }
    
            public Analyse AnalyseTimeQuickSort()
            {
                Analyse a = AnalyseSort(QuickSort);
                return a;
            }
    
            public Analyse AnalyseTimeHeapSort()
            {
                Analyse a = AnalyseSort(PyramidSort);
                return a;
            }
    
            public Analyse AnalyseTimeMergeSort()
            {
                Analyse a = AnalyseSort(SortMerge);
                return a;
            }
        }
    }
    
    


    Назад Вперед Зміст