Как реализовать автоматическое обновление listView win forms c#?

Суть в том, что при нажатии кнопки добавить должно сразу же отображаться поле в richtextbox, а получается что только при следующем добавлении поля, ранее добавленное поле отображается в виде запроса, а второе соответственно нет и так далее. Можно ли изменить это как-либо, уже пробовал делать многое, что-то не получается.

Главный метод UpdateSQLQuery. Еще важный момент, может есть какой-нибудь метод который сразу же обновляется при изменении в DataGridView и выводит нам незамедлительно результат. В общем, нужна помощь более опытного.

Архив проекта прикреплю.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Web;
using System.Data.SQLite;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using System.Reflection.Emit;

namespace DB_Broser_for_SQLite
{
    public partial class CreateTableForm : Form
    {
        public event Action<string> DataPassed;

        private string tableName;
        private DataTable schema;
        private bool isEditMode = false;

        private string dbFilePath;
        public CreateTableForm(string dbFilePath)
        {
            InitializeComponent();
            InitializeDataGridView();
            textBox1.TextChanged += textBox1_TextChanged;// Подключаем обработчик событий
            dataGridView1.CellValueChanged += dataGridView1_CellValueChanged;
            dataGridView1.CellContentClick += dataGridView1_CellContentClick;// Подключаем обработчик событий

            this.dbFilePath = dbFilePath;
            // Здесь можно добавить код для работы с базой данных
        }

        public void SetButtonText(string text)
        {
            button1.Text = text;
        }

        public void SetEditMode(string buttonText, DataTable schema, string tableName)
        {
            button1.Text = buttonText; // Change button text to "Изменить"
            this.tableName = tableName; // Store the table name
            this.isEditMode = true; // Set edit mode to true
            LoadTableDataFromSchema(schema, tableName); // Load existing schema data into the form fields
        }

        public class TableField
        {
            public string Name { get; set; }
            public string Type { get; set; }
            public bool IsNotNull { get; set; }
        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            int newRowIndex = dataGridView1.Rows.Add();
            DataGridViewRow newRow = dataGridView1.Rows[newRowIndex];

            newRow.Cells["Name"].Value = "Field" + (newRowIndex + 1); // Условное имя поля
            newRow.Cells["Type"].Value = "INTEGER"; // Тип данных
            //UpdateSQLQuery();
        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void InitializeDataGridView()
        {
            dataGridView1.Columns.Clear(); // Очищаем предыдущие столбцы, если они есть
            dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "Name", HeaderText = "Имя" });

            // Добавляем ComboBox для типов данных
            var typeColumn = new DataGridViewComboBoxColumn
            {
                Name = "Type",
                HeaderText = "Тип",
                DataSource = new List<string> { "INTEGER", "TEXT", "REAL", "BLOB" } // Пример типов данных
            };
            dataGridView1.Columns.Add(typeColumn);

            // Добавляем CheckBox для Not Null
            dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn { Name = "NotNull", HeaderText = "Not Null" });
            // Добавляем CheckBox для Primary Key
            dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn { Name = "PrimaryKey", HeaderText = "Первичный ключ" });

            // Добавляем CheckBox для Auto Increment
            dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn { Name = "AutoIncrement", HeaderText = "Автокремент" });

            // Добавляем CheckBox для Unique
            dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn { Name = "Unique", HeaderText = "Уникальный" });

        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            UpdateSQLQuery();
        }

        private void UpdateSQLQuery()
        {
            string tableName = textBox1.Text.Trim();
            if (!string.IsNullOrEmpty(tableName))
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("CREATE TABLE \"{0}\" (\n", tableName);
                List<string> fields = new List<string>();
                string primaryKey = null;
                bool hasPrimaryKey = false;

                for (int i = 0; i < dataGridView1.Rows.Count - 1; i++) // -1 чтобы избежать пустой строки
                {
                    var row = dataGridView1.Rows[i];
                    string fieldName = row.Cells["Name"].Value?.ToString();
                    string fieldType = row.Cells["Type"].Value?.ToString();
                    bool isNotNull = row.Cells["NotNull"].Value != null && (bool)row.Cells["NotNull"].Value;
                    bool isPrimaryKey = row.Cells["PrimaryKey"].Value != null && (bool)row.Cells["PrimaryKey"].Value;
                    bool isAutoIncrement = row.Cells["AutoIncrement"].Value != null && (bool)row.Cells["AutoIncrement"].Value;
                    bool isUnique = row.Cells["Unique"].Value != null && (bool)row.Cells["Unique"].Value;
                    if (!string.IsNullOrEmpty(fieldName) && !string.IsNullOrEmpty(fieldType))
                    {
                        var fieldDefinition = new StringBuilder();
                        fieldDefinition.AppendFormat("    \"{0}\" {1}", fieldName, fieldType);
                        if (isNotNull)
                        {
                            fieldDefinition.Append(" NOT NULL");
                        }
                        if (isUnique)
                        {
                            fieldDefinition.Append(" UNIQUE");
                        }
                        fields.Add(fieldDefinition.ToString());
                        // Проверяем на первичный ключ
                        if (isPrimaryKey)
                        {
                            if (isAutoIncrement)
                            {
                                primaryKey = $"PRIMARY KEY(\"{fieldName}\" AUTOINCREMENT)";
                            }
                            else
                            {
                                primaryKey = $"PRIMARY KEY(\"{fieldName}\")";
                            }
                            hasPrimaryKey = true;
                        }
                    }
                }

                // Добавляем все поля в StringBuilder с запятой между ними
                if (fields.Count > 0)
                {
                    sb.AppendLine(string.Join(",\n", fields) + ",");
                }

                // Если есть первичный ключ, добавляем его без лишней запятой
                if (hasPrimaryKey && !string.IsNullOrEmpty(primaryKey))
                {
                    sb.AppendLine(primaryKey);
                }

                sb.Append(");");
                richTextBox1.Text = sb.ToString();
            }
            else
            {
                richTextBox1.Text = string.Empty; // Очистка RichTextBox, если поле пустое
            }
        }

        private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            // Обновляем SQL-запрос после изменения значения
            UpdateSQLQuery();

            if (e.RowIndex >= 0 && (e.ColumnIndex == 3 || e.ColumnIndex == 4)) // 3 - PrimaryKey, 4 - AutoIncrement
            {

                var row = dataGridView1.Rows[e.RowIndex];

                // Обработка изменения AutoIncrement
                if (e.ColumnIndex == 4) // AutoIncrement
                {
                    bool isAutoIncrementChecked = row.Cells["AutoIncrement"].Value != null && (bool)row.Cells["AutoIncrement"].Value;

                    if (isAutoIncrementChecked)
                    {
                        foreach (DataGridViewRow r in dataGridView1.Rows)
                        {
                            if (r.Index != e.RowIndex && (r.Cells["AutoIncrement"].Value != null && (bool)r.Cells["AutoIncrement"].Value))
                            {
                                r.Cells["AutoIncrement"].Value = false; // Убираем отметку с другого AutoIncrement
                            }
                        }
                    }
                }

                // Обработка изменения PrimaryKey
                if (e.ColumnIndex == 3) // PrimaryKey
                {
                    bool isPrimaryKeyChecked = row.Cells["PrimaryKey"].Value != null && (bool)row.Cells["PrimaryKey"].Value;

                    if (isPrimaryKeyChecked)
                    {
                        foreach (DataGridViewRow r in dataGridView1.Rows)
                        {
                            if (r.Index != e.RowIndex && (r.Cells["PrimaryKey"].Value != null && (bool)r.Cells["PrimaryKey"].Value))
                            {
                                r.Cells["PrimaryKey"].Value = false; // Убираем отметку с другого PrimaryKey
                            }
                        }
                    }
                }

                // Устанавливаем PrimaryKey для текущей строки, если AutoIncrement установлен
                if (row.Cells["AutoIncrement"].Value != null && (bool)row.Cells["AutoIncrement"].Value)
                {
                    row.Cells["PrimaryKey"].Value = true; // Устанавливаем PrimaryKey для текущей строки
                }
            }
        }

        public void LoadTableDataFromSchema(DataTable schemaTable, string tableName)
        {
            // Set the table name in textBox1
            textBox1.Text = tableName;

            // Clear existing rows in the DataGridView
            dataGridView1.Rows.Clear();

            // Populate the DataGridView with the schema data
            foreach (DataRow row in schemaTable.Rows)
            {
                int newRowIndex = dataGridView1.Rows.Add();
                DataGridViewRow newRow = dataGridView1.Rows[newRowIndex];

                // Fill in the DataGridView cells with the schema information
                newRow.Cells["Name"].Value = row["name"]; // Column name
                newRow.Cells["Type"].Value = row["type"]; // Data type

                // Check for NOT NULL constraint
                newRow.Cells["NotNull"].Value = row["notnull"].ToString() == "1"; // 1 indicates NOT NULL

                // Check for PRIMARY KEY constraint
                newRow.Cells["PrimaryKey"].Value = row["pk"].ToString() == "1"; // 1 indicates PRIMARY KEY

                // Auto Increment is not directly available, but can be inferred if it's a PRIMARY KEY and INTEGER
                newRow.Cells["AutoIncrement"].Value = (row["pk"].ToString() == "1" && row["type"].ToString().ToUpper().Contains("INTEGER"));

                // Unique constraint is not directly available, consider adding a separate logic if needed
                newRow.Cells["Unique"].Value = false; // Default to false, adjust as necessary
            }

            // Update the SQL query based on the loaded schema
            UpdateSQLQuery(); // Call this to reflect the loaded data in the SQL query box

            // Set the SQL code in richTextBox1
            richTextBox1.Text = GenerateCreateTableSQL(schemaTable, tableName);
        }

        private string GenerateCreateTableSQL(DataTable schemaTable, string tableName)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("CREATE TABLE \"{0}\" (\n", tableName);
            List<string> fields = new List<string>();
            string primaryKey = null;
            bool hasPrimaryKey = false;

            foreach (DataRow row in schemaTable.Rows)
            {
                string fieldName = row["name"].ToString();
                string fieldType = row["type"].ToString();
                bool isNotNull = row["notnull"].ToString() == "1";
                bool isPrimaryKey = row["pk"].ToString() == "1";
                bool isAutoIncrement = isPrimaryKey && fieldType.ToUpper().Contains("INTEGER");

                var fieldDefinition = new StringBuilder();
                fieldDefinition.AppendFormat("    \"{0}\" {1}", fieldName, fieldType);
                if (isNotNull)
                {
                    fieldDefinition.Append(" NOT NULL");
                }
                if (isPrimaryKey)
                {
                    if (isAutoIncrement)
                    {
                        primaryKey = $"PRIMARY KEY(\"{fieldName}\" AUTOINCREMENT)";
                    }
                    else
                    {
                        primaryKey = $"PRIMARY KEY(\"{fieldName}\")";
                    }
                    hasPrimaryKey = true;
                }
                fields.Add(fieldDefinition.ToString());
            }

            if (fields.Count > 0)
            {
                sb.AppendLine(string.Join(",\n", fields) + ",");
            }

            if (hasPrimaryKey && !string.IsNullOrEmpty(primaryKey))
            {
                sb.AppendLine(primaryKey);
            }

            sb.Append(");");
            return sb.ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (isEditMode)
            {
                SaveChangesToTable();
                this.Close();
            }
            else
            {
                // Получаем SQL-запрос из RichTextBox
                string sql = richTextBox1.Text;

                // Проверяем, не пустой ли SQL-запрос
                if (string.IsNullOrWhiteSpace(sql))
                {
                    MessageBox.Show("Пожалуйста, введите SQL-запрос.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                // Выполняем SQL-запрос
                ExecuteSQL(sql);

                // Закрываем форму после выполнения запроса (по желанию)
                this.Close();

            }
        }

        private void SaveChangesToTable()
        {
            using (var connection = new SQLiteConnection($"Data Source={dbFilePath};Version=3;"))
            {
                connection.Open();

                // Получаем новое имя таблицы из textBox1
                string newTableName = textBox1.Text.Trim();

                // Проверяем, изменилось ли имя таблицы
                if (newTableName != tableName)
                {
                    // Переименовываем таблицу
                    string renameTableQuery = $"ALTER TABLE \"{tableName}\" RENAME TO \"{newTableName}\";";
                    using (var renameCommand = new SQLiteCommand(renameTableQuery, connection))
                    {
                        renameCommand.ExecuteNonQuery();
                    }
                    tableName = newTableName; // Обновляем локальную переменную tableName
                }

                // Получаем список существующих столбцов
                var existingColumns = new HashSet<string>();
                using (var schemaCommand = new SQLiteCommand($"PRAGMA table_info(\"{tableName}\");", connection))
                using (var reader = schemaCommand.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        existingColumns.Add(reader["name"].ToString());
                    }
                }

                // Теперь сохраняем изменения в полях
                foreach (DataGridViewRow row in dataGridView1.Rows)
                {
                    if (row.IsNewRow) continue; // Пропускаем пустую строку

                    string fieldName = row.Cells["Name"].Value?.ToString();
                    string fieldType = row.Cells["Type"].Value?.ToString();
                    bool isNotNull = row.Cells["NotNull"].Value != null && (bool)row.Cells["NotNull"].Value;
                    bool isPrimaryKey = row.Cells["PrimaryKey"].Value != null && (bool)row.Cells["PrimaryKey"].Value;
                    bool isAutoIncrement = row.Cells["AutoIncrement"].Value != null && (bool)row.Cells["AutoIncrement"].Value;
                    bool isUnique = row.Cells["Unique"].Value != null && (bool)row.Cells["Unique"].Value;

                    // Проверяем, существует ли уже столбец
                    if (!existingColumns.Contains(fieldName))
                    {
                        // Строим запрос ALTER TABLE для добавления новых полей
                        StringBuilder addFieldQuery = new StringBuilder($"ALTER TABLE \"{tableName}\" ADD COLUMN \"{fieldName}\" {fieldType}");

                        if (isNotNull)
                        {
                            addFieldQuery.Append(" NOT NULL");
                        }
                        if (isUnique)
                        {
                            addFieldQuery.Append(" UNIQUE");
                        }
                        if (isPrimaryKey)
                        {
                            addFieldQuery.Append(" PRIMARY KEY");
                        }
                        if (isAutoIncrement)
                        {
                            addFieldQuery.Append(" AUTOINCREMENT");
                        }

                        using (var addFieldCommand = new SQLiteCommand(addFieldQuery.ToString(), connection))
                        {
                            addFieldCommand.ExecuteNonQuery();
                        }

                        // Добавляем новый столбец в список существующих столбцов
                        existingColumns.Add(fieldName);
                    }
                }

                MessageBox.Show("Изменения успешно сохранены.", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        private void ExecuteSQL(string sql)
        {
            try
            {
                using (var connection = new SQLiteConnection($"Data Source={dbFilePath};Version=3;")) // Используйте ваш тип базы данных
                {
                    connection.Open();
                    using (var command = new SQLiteCommand(sql, connection))
                    {
                        command.ExecuteNonQuery(); // Выполняем SQL-запрос
                    }
                }
                MessageBox.Show("Таблица успешно создана!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Ошибка при выполнении запроса: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            if (dataGridView1.IsCurrentCellDirty)
            {
                // Фиксируем изменения в текущей ячейке
                dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
                UpdateSQLQuery();
            }
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            // Проверяем, есть ли выбранные строки
            if (dataGridView1.SelectedRows.Count > 0)
            {
                foreach (DataGridViewRow selectedRow in dataGridView1.SelectedRows)
                {
                    if (!selectedRow.IsNewRow) // Убедитесь, что это не новая строка
                    {
                        // Получаем имя поля для удаления
                        string fieldName = selectedRow.Cells["Name"].Value.ToString();
                        dataGridView1.Rows.Remove(selectedRow); // Удаляем строку из DataGridView

                        // Удаляем поле из базы данных
                        RemoveFieldFromDatabase(fieldName);
                    }
                }

                // Обновляем SQL-запрос после удаления
                UpdateSQLQuery();
            }
            else
            {
                MessageBox.Show("Пожалуйста, выберите поле для удаления.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void RemoveFieldFromDatabase(string fieldName)
        {
            using (var connection = new SQLiteConnection($"Data Source={dbFilePath};Version=3;"))
            {
                connection.Open();

                // Получаем текущее имя таблицы
                string currentTableName = tableName;

                // Получаем схему текущей таблицы
                var schemaTable = new DataTable();
                using (var schemaCommand = new SQLiteCommand($"PRAGMA table_info(\"{currentTableName}\");", connection))
                using (var reader = schemaCommand.ExecuteReader())
                {
                    schemaTable.Load(reader);
                }

                // Создаем новую таблицу с необходимыми полями
                var createTableQuery = new StringBuilder();
                createTableQuery.AppendFormat("CREATE TABLE \"new_{0}\" (", currentTableName);

                List<string> fields = new List<string>();
                foreach (DataRow row in schemaTable.Rows)
                {
                    string name = row["name"].ToString();
                    if (name != fieldName) // Пропускаем удаляемое поле
                    {
                        string type = row["type"].ToString();
                        bool isNotNull = row["notnull"].ToString() == "1";
                        bool isPrimaryKey = row["pk"].ToString() == "1";

                        var fieldDefinition = new StringBuilder();
                        fieldDefinition.AppendFormat("    \"{0}\" {1}", name, type);
                        if (isNotNull) fieldDefinition.Append(" NOT NULL");
                        fields.Add(fieldDefinition.ToString());
                    }
                }

                if (fields.Count > 0)
                {
                    createTableQuery.AppendLine(string.Join(",\n", fields));
                }
                createTableQuery.Append(");");

                // Создаем новую таблицу
                using (var createCommand = new SQLiteCommand(createTableQuery.ToString(), connection))
                {
                    createCommand.ExecuteNonQuery();
                }

                // Копируем данные из старой таблицы в новую
                var insertQuery = new StringBuilder();
                insertQuery.AppendFormat("INSERT INTO \"new_{0}\" ({1}) SELECT {1} FROM \"{0}\";",
                    currentTableName, string.Join(", ", fields.Select(f => f.Split(' ')[0]))); // Выбираем только имена полей

                using (var insertCommand = new SQLiteCommand(insertQuery.ToString(), connection))
                {
                    insertCommand.ExecuteNonQuery();
                }

                // Удаляем старую таблицу
                using (var dropCommand = new SQLiteCommand($"DROP TABLE \"{currentTableName}\";", connection))
                {
                    dropCommand.ExecuteNonQuery();
                }

                // Переименовываем новую таблицу
                using (var renameCommand = new SQLiteCommand($"ALTER TABLE \"new_{currentTableName}\" RENAME TO \"{currentTableName}\";", connection))
                {
                    renameCommand.ExecuteNonQuery();
                }

                MessageBox.Show($"Поле \"{fieldName}\" успешно удалено.", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }
}

Код второй формы, где нужно все создается таблица.


Ответы (1 шт):

Автор решения: Ефрем90 Ельников

Я нашел решение в этой строчке кода. Моя ошибка. for (int i = 0; i < dataGridView1.Rows.Count - 1; i++) - это неправильно. Нужно for (int i = 0; i < dataGridView1.Rows.Count; i++) и тогда все будет так как надо. Работайте через дебаг он помогает.

→ Ссылка