Ошибка создания DataGridView, когда AllowUserToAddRows имеет значение true - PullRequest
0 голосов
/ 12 июля 2020

У меня есть приложение базы данных ms-access в C#. Данные таблиц привязаны к DataGridView в C#. Я добавил в мою таблицу новое поле CheckBox с именем Check.

Когда AllowUserToAddRows установлено на false. При загрузке DGV ошибка не генерируется.

Если AllowUserToAddRows установлено на True. При загрузке DGV генерируется ошибка. Ошибка находится под: -

введите описание изображения здесь

DGV находится в дочерней форме. Его код приведен ниже.

public partial class frmStudents : Form
{
    // Declaration
    private DataTable dTable;
    public frmStudents()
    {
        InitializeComponent();
        
    }

    private void frmStudents_Load(object sender, EventArgs e)
    {
        LoadTheme();

        // Show Students
        StudentsLoadDGV();
    }
    private void LoadTheme()
    {
        //foreach (Control btns in this.Controls)  Check all controls in Form
        foreach(Button btns in this.Controls.OfType<Button>())      // Check only buttons in Form
        {
            if (btns.GetType() == typeof(Button))
            {
                Button btn = (Button)btns;
                btn.BackColor = ThemeColor.PrimaryColor;
                btn.ForeColor = Color.White;
                btn.FlatAppearance.BorderColor = ThemeColor.SecondaryColor;
            }
        }
    }
    // Getting data from Database to DataTable
    private DataTable StudentsDTable()
    {
        DataTable dt = new DataTable();
        using (var conn = new OleDbConnection(DatabaseObjects.ConnectionString))
        {
            OleDbCommand command = new OleDbCommand("SELECT s.Check, " +
            "DCount("RollNo","students","RollNo <=" & [RollNo]) AS SrNo, s.RollNo, s.SName, "+ 
            "s.FName, s.DOB, c.Class, s.[Section], s.Picture FROM students AS s LEFT JOIN classes "+ 
            "AS c ON s.ClassID = c.ClassID ORDER BY s.RollNo", conn);
            conn.Open();
            dt.Load(command.ExecuteReader());
        }
        return dt;
    }

    // Loading DataTable into DataGridView
    private void StudentsLoadDGV()
    {
        dTable = StudentsDTable();
        dgvDisplay.DataSource = dTable;
                    // Change Column Headings
        dgvDisplay.Columns["SrNo"].HeaderText = "Sr No";
        dgvDisplay.Columns["RollNo"].HeaderText = "Roll No";
        dgvDisplay.Columns["SName"].HeaderText = "Student Name";
        dgvDisplay.Columns["FName"].HeaderText = "Father Name";
        dgvDisplay.Columns["DOB"].HeaderText = "Date of Birth";
        //dgvDisplay.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
        
    }

    private void btnNew_Click(object sender, EventArgs e)
    {
        DialogResult result;
        using (var conn = new OleDbConnection(DatabaseObjects.ConnectionString))
        {
            OleDbCommand command = new OleDbCommand("select * from Classes", conn);
            conn.Open(); 
            dTable = new DataTable();
            dTable.Load(command.ExecuteReader());
            frmStudentProfile form = new frmStudentProfile(dTable, "New");
            result = form.ShowDialog();
        }
        if (result == DialogResult.OK)
            StudentsLoadDGV();
    }

    private void btnEdit_Click(object sender, EventArgs e)
    {
        if (!ValidSelection())
            return;

        DialogResult result;
        // Get the index of the row of selected cell, then get the RollNo from the clicked row and pass it to the command
        int index  = dgvDisplay.SelectedCells[0].RowIndex;
        var selectedRollNo = dgvDisplay.Rows[index].Cells["RollNo"].Value;
        using (var conn = new OleDbConnection(DatabaseObjects.ConnectionString))
        {
            string query = "select s.RollNo, s.SName, s.FName, s.DOB, c.Class, c.ClassID, s.[Section], s.Picture from Classes as c " +
                "left outer join (select * from Students where RollNo = @RollNo) as s on s.ClassID = c.ClassID";
            using(OleDbCommand command = new OleDbCommand(query, conn))
            {
                command.Parameters.Add(new OleDbParameter("RollNo", selectedRollNo));
                dTable = new DataTable();
                conn.Open();
                dTable.Load(command.ExecuteReader());
                frmStudentProfile form = new frmStudentProfile(dTable, "default");
                result = form.ShowDialog();
            }
        }
        if(result == DialogResult.OK)
            StudentsLoadDGV();
    }

    private void dgvDisplay_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
    {
        if (!ValidSelection())
            return;
        
        DialogResult result;
        // Get row number that was clicked
        var index = e.RowIndex;
        // get the RollNo from the clicked row and pass it to the command
        var selectedRollNo = dgvDisplay.Rows[index].Cells["RollNo"].Value;
        using (var conn = new OleDbConnection(DatabaseObjects.ConnectionString))
        {
            string query = "select s.RollNo, s.SName, s.FName, s.DOB, c.Class, c.ClassID, s.[Section], s.Picture from Classes as c " +
                "left outer join (select * from Students where RollNo = @RollNo) as s on s.ClassID = c.ClassID";
            using (OleDbCommand command = new OleDbCommand(query, conn))
            {
                command.Parameters.Add(new OleDbParameter("RollNo", selectedRollNo));
                dTable = new DataTable();
                conn.Open();
                dTable.Load(command.ExecuteReader());
                frmStudentProfile form = new frmStudentProfile(dTable, "default");
                result = form.ShowDialog();
            }
        }
        if (result == DialogResult.OK)
            StudentsLoadDGV();
    }

    private bool ValidSelection()
    {
        bool isValid = true;
        string errorMsg = "";
        if (dgvDisplay.SelectedRows.Count > 1 )
        {
            errorMsg += "- Select one Record which you want to Edit.";
            isValid = false;
        }
        else if((dgvDisplay.SelectedCells.Cast<DataGridViewCell>().Select(c => c.RowIndex).Distinct().Count() > 1))
        {
            errorMsg += "- Select Cells of one Record which you want to Edit.";
            isValid = false;
        }
        
        if(!isValid)
        {
            MessageBox.Show(errorMsg, "Invalid Selection", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        return isValid;
    }
}

Как мне удалить указанную выше ошибку ??

Ответы [ 2 ]

1 голос
/ 19 июля 2020

Проблема в стороне клиента; таблица данных, подключенная к сетке студентов, имеет столбец «Проверить», который является логическим, но не имеет значения по умолчанию. Это проблема, если сетка данных пытается добавить новую строку в нижней части сетки. Сетка данных, связанная с таблицей данных, вызовет datatable.NewRow () для получения новой строки с предлагаемыми значениями по умолчанию для отображения в нижней части сетки. Если пользователь вводит в эту строку, затем переходит в другое место, строка будет зафиксирована в таблице данных. Поскольку в вашем столбце Check отсутствует значение по умолчанию, он будет равен Null в отдельной строке, возвращаемой NewRow, а столбец comboboxcolumn DataGridView будет задыхаться от него, потому что ему нужно значение true или false, а не null

Помещение этой строки кода в ваш метод StudentDTable после загрузки таблицы прекратит появление ошибки:

dt.Columns["Check"].DefaultValue = false;

Но это не совсем то, что нужно делать, потому что вы не делаете доступ к данным правильным образом для работы на основе таблиц данных. Установка этого значения по умолчанию позволит сетке отображать новую строку, а затем пользователь может ввести ее, зафиксировать строку et c .. Проблема в том, что у них действительно нет способа сохранить эту новую строку (вы не не используйте адаптеры для записи данных в кэшированные данные в базу данных, вы делаете весь доступ к данным напрямую), и у вас уже есть модальный диалог, который добавляет новые строки, поэтому я не уверен, почему вы хотите запускать свой datagridview в режиме AllowUserToAddRows = true в любом случае

Множество написанного вами кода наводит меня на мысль, что вы рассматриваете DataGridView как своего рода контейнер для данных, но это не намерение дизайна - они просто показывают данные, которые они находят в чем-то еще (DataTable в этом случае), и вы должны манипулировать something_else, если хотите манипулировать данными, а не выкапывать их из представления

0 голосов
/ 16 июля 2020

Хорошо, если в таблице данных отображается строка false, вам нужно изменить свой запрос, чтобы преобразовать false в 0 и true в 1.

 private DataTable StudentsDTable()
    {
        DataTable dt = new DataTable();
        using (var conn = new OleDbConnection(DatabaseObjects.ConnectionString))
        {
            OleDbCommand command = new OleDbCommand("SELECT IIf(s.Check = true, 1, 0) AS Check, " +
            "DCount("RollNo","students","RollNo <=" & [RollNo]) AS SrNo, s.RollNo, s.SName, "+ 
            "s.FName, s.DOB, c.Class, s.[Section], s.Picture FROM students AS s LEFT JOIN classes "+ 
            "AS c ON s.ClassID = c.ClassID ORDER BY s.RollNo", conn);
            conn.Open();
            dt.Load(command.ExecuteReader());
        }
        return dt;
    }

См. Оператор Microsoft Access IIf для IIf.

Дайте мне знать, работает ли это или нет.

Извините, обновил свой ответ так, чтобы true = 1 вместо -1. Также изменено \"true\" на true.

...