mardi 21 juin 2016

Trouble Getting DataGridView to Work with ComboBox Dropdown

I need some help getting my code to work. DataGridView is proving much more complex that I had anticipated. I need someone to please show me how to fix my code, so that both the DataGridView control can be updated and my DataGridViewComboBoxColumn dropdown and DataGridViewCheckBoxColumn controls all work. I'm okay with any strategy, provided the solution you offer is somewhat elegant and complete. I've already spent far too much time trying to figure this out on my own. Any thoughts or suggestions would be greatly appreciated.

Here is a simplifcation of what my backend looks like:

MySqlDataAdapter dataAdapter = new MySqlDataAdapter(sqlRequestString, this.dbConnection);
MySqlCommandBuilder commandBuilder = new MySqlCommandBuilder(dataAdapter);
DataTable table = new DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
dataAdapter.Fill(table);
bindingSource.DataSource = table;

If I get rid of the BindingSource, how do I connect the DataTable directly to the DataGridView, so that the ComboBox and Checkbox columns are properly populated?

UPDATE

This should be a complete overview of how I am attempting to initialize my DataGridView:

private void InitializeComponent()
{

/* ... */

this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
    this.DataGridViewColumn_Section,
    this.DataGridViewColumn_Indent,
    this.DataGridViewColumn_Content,
    this.DataGridViewColumn_Summary,
    this.DataGridViewColumn_Role,
    this.DataGridViewColumn_Author,
    this.DataGridViewColumn_Updated});
    this.dataGridView1.Name = "dataGridView1";
    this.dataGridView1.DataSourceChanged += new System.EventHandler(this.dataGridView1_DataSourceChanged);
    this.dataGridView1.CellEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellEnter);
    this.dataGridView1.CellLeave += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellLeave);
    this.dataGridView1.ColumnAdded += new System.Windows.Forms.DataGridViewColumnEventHandler(this.dataGridView1_ColumnAdded);
    this.dataGridView1.SelectionChanged += new System.EventHandler(this.dataGridView1_SelectionChanged);
    this.dataGridView1.Leave += new System.EventHandler(this.dataGridView1_Leave);
    // 
    // DataGridViewColumn_Section
    // 
    this.DataGridViewColumn_Section.HeaderText = "Section";
    this.DataGridViewColumn_Section.Name = "DataGridViewColumn_Section";
    // 
    // DataGridViewColumn_Indent
    // 
    this.DataGridViewColumn_Indent.HeaderText = "Indent";
    this.DataGridViewColumn_Indent.Name = "DataGridViewColumn_Indent";
    // 
    // DataGridViewColumn_Content
    // 
    this.DataGridViewColumn_Content.HeaderText = "Content";
    this.DataGridViewColumn_Content.MinimumWidth = 100;
    this.DataGridViewColumn_Content.Name = "DataGridViewColumn_Content";
    // 
    // DataGridViewColumn_Summary
    // 
    this.DataGridViewColumn_Summary.HeaderText = "Summary";
    this.DataGridViewColumn_Summary.Name = "DataGridViewColumn_Summary";
    // 
    // DataGridViewColumn_Role
    // 
    this.DataGridViewColumn_Role.HeaderText = "Minimum Signoff";
    this.DataGridViewColumn_Role.Name = "DataGridViewColumn_Role";
    // 
    // DataGridViewColumn_Author
    // 
    this.DataGridViewColumn_Author.HeaderText = "Author";
    this.DataGridViewColumn_Author.Name = "DataGridViewColumn_Author";
    this.DataGridViewColumn_Author.ReadOnly = true;
    // 
    // DataGridViewColumn_Updated
    // 
    this.DataGridViewColumn_Updated.HeaderText = "Updated";
    this.DataGridViewColumn_Updated.Name = "DataGridViewColumn_Updated";
    this.DataGridViewColumn_Updated.ReadOnly = true;

/* ... */

}

public MyWinform()
{
    InitializeComponent();

    // Initialize DataGridView DataTable
    this.dgvDataTable = new DataTable();

    // Initialize DataGridView column indexes
    this.idxSection = dataGridView1.Columns["DataGridViewColumn_Section"].Index;
    this.idxIndent = dataGridView1.Columns["DataGridViewColumn_Indent"].Index;
    this.idxContent = dataGridView1.Columns["DataGridViewColumn_Content"].Index;
    this.idxSummary = dataGridView1.Columns["DataGridViewColumn_Summary"].Index;
    this.idxRole = dataGridView1.Columns["DataGridViewColumn_Role"].Index;
    this.idxAuthor = dataGridView1.Columns["DataGridViewColumn_Author"].Index;
    this.idxLastUpdate = dataGridView1.Columns["DataGridViewColumn_Updated"].Index;
}

private void MyWinform_Load(object sender, EventArgs e)
{
    DataGridView dgv = this.dataGridView1;
    DataGridViewComboBoxColumn comboCol;

    // Load System Menu
    SystemMenu.Load(this.Handle);

    // Insert selection prompt
    ProcTemplateRecord selectProcPrompt = new ProcTemplateRecord();
    selectProcPrompt.PrimaryKey = 0;
    selectProcPrompt.ProcName = "Select from the list...";
    this.procList.Insert(0, selectProcPrompt);

    // Add new procedure prompt
    ProcTemplateRecord newProcPrompt = new ProcTemplateRecord();
    newProcPrompt.PrimaryKey = -1;
    newProcPrompt.ProcName = "Start a new Safe Job Procedure";
    this.procList.Add(newProcPrompt);

    // Finish initializing the ComboBox dropdown list
    this.comboBox1.DataSource = this.procList;
    this.comboBox1.DisplayMember = "ProcName";
    this.comboBox1.ValueMember = "PrimaryKey";

    // Finish initializing DataGridView and bind to BindingSource
    this.dataGridView1.AutoGenerateColumns = false;

/*
    // Finish initializing the DataGridView ComboBox columns...
    comboCol = (DataGridViewComboBoxColumn)dgv.Columns[this.idxSection];
    comboCol.DataSource = Enum.GetValues(typeof(SectionType));
    comboCol.ValueType = typeof(SectionType);
    comboCol.DropDownWidth = ComboBoxMaxLabelWidth(comboCol);

    comboCol = (DataGridViewComboBoxColumn)dgv.Columns[this.idxRole];
    comboCol.DataSource = Enum.GetValues(typeof(RoleType));
    comboCol.ValueType = typeof(RoleType);
    comboCol.DropDownWidth = ComboBoxMaxLabelWidth(comboCol);

    this.dataGridView1.DataSource = this.dgvDataTable;
*/
    this.RefreshDataGridViewColumnWidths();

    // Setup post-initialization DataGridViewEvent handlers
    this.dataGridView1.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellValueChanged);
    this.dataGridView1.CurrentCellDirtyStateChanged += new System.EventHandler(this.dataGridView1_CurrentCellDirtyStateChanged);
}

private void dataGridView1_DataSourceChanged(object sender, EventArgs e)
{
    this.RefreshDataGridViewColumnWidths();
}

private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
    DataGridView dgv = (DataGridView)sender;

    this.RefreshButtons();

    if (e.ColumnIndex == this.idxSection)
    {
        this.label_dgvToolTip.Visible = false;
    }
    else if (e.ColumnIndex == this.idxIndent)
    {
        this.label_dgvToolTip.Visible = false;
    }
    else if (e.ColumnIndex == this.idxContent)
    {
        this.label_dgvToolTip.Visible = false;
    }
    else if (e.ColumnIndex == this.idxSummary)
    {
        this.label_dgvToolTip.Visible = false;
    }
    else if (e.ColumnIndex == this.idxRole)
    {
        this.label_dgvToolTip.Visible = false;
    }
    else if (e.ColumnIndex == this.idxAuthor)
    {
        this.label_dgvToolTip.Visible = false;
        this.label_dgvToolTip.Text = "Author column values are read only.";
        this.label_dgvToolTip.Visible = true;
    }
    else if (e.ColumnIndex == this.idxLastUpdate)
    {
        this.label_dgvToolTip.Visible = false;
        this.label_dgvToolTip.Text = "Updated column values are read only.";
        this.label_dgvToolTip.Visible = true;
    }
    else
    {
        this.label_dgvToolTip.Visible = false;
    }

    this.idxActiveColumn = e.ColumnIndex;
    this.idxActiveRow = e.RowIndex;
}

private void dataGridView1_CellLeave(object sender, DataGridViewCellEventArgs e)
{
    this.label_dgvToolTip.Visible = false;
    this.RefreshButtons();
}

private void dataGridView1_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
    DataGridView dgv = this.dataGridView1;

    if ((e.Column.DataPropertyName == "PageSection") &&
        (e.Column.CellType != typeof(DataGridViewComboBoxCell)))
    {
        var cbo = GetComboBoxColumn(e.Column);
        cbo.DataSource = Enum.GetValues(typeof(SectionType));
        cbo.ValueType = typeof(SectionType);
        dgv.Columns.Remove(e.Column);
        dgv.Columns.Add(cbo);
    }
    else if ((e.Column.DataPropertyName == "UserRole") &&
        (e.Column.CellType != typeof(DataGridViewComboBoxCell)))
    {
        var cbo = GetComboBoxColumn(e.Column);
        cbo.DataSource = Enum.GetValues(typeof(RoleType));
        cbo.ValueType = typeof(RoleType);
        dgv.Columns.Remove(e.Column);
        dgv.Columns.Add(cbo);
    }
}

private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
    this.RefreshButtons();
}

private void dataGridView1_Leave(object sender, EventArgs e)
{
    DataGridView dgv = this.dataGridView1;

    if (dgv.SelectedCells.Count == 0)
    {
        this.idxActiveColumn = -1;
        this.idxActiveRow = -1;
    }
}

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    DataGridView dgv = (DataGridView)sender;
    DataGridViewComboBoxCell sectionCell = (DataGridViewComboBoxCell)dgv.Rows[e.RowIndex].Cells[this.idxSection];
    DataGridViewTextBoxCell indentCell = (DataGridViewTextBoxCell)dgv.Rows[e.RowIndex].Cells[this.idxIndent];
    DataGridViewComboBoxCell roleCell = (DataGridViewComboBoxCell)dgv.Rows[e.RowIndex].Cells[this.idxRole];
    Int32 colIndex = e.ColumnIndex;

    try
    {
        if (colIndex == this.idxIndent)
        {
            int number;
            string cellValue = indentCell.Value.ToString();
            bool isNumeric = int.TryParse(cellValue, out number);

            if (!isNumeric)
            {
                cellValue = cellValue.Substring(0, cellValue.Length - 1);
                indentCell.Value = cellValue;
            }
        }

        // Column resizing code goes last
        this.RefreshDataGridViewColumnWidths();

        this.dgvIsDirty = true;
    }
    catch (Exception ex)
    {
        throw new Exception("Failed to refresh DataGridView on cell change.", ex);
    }
}

private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    DataGridView dgv = (DataGridView)sender;

    try
    {
        if (dgv.IsCurrentCellDirty)
        {
            // This fires the cell value changed handler below
            dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);
            this.RefreshDataGridViewColumnWidths();
        }
    }
    catch (Exception ex)
    {
        throw new Exception("Failed to commit edit of DataGridView cell.", ex);
    }
}

This is the code I am using to update my DataGridView contorl:

// Load the data from the database into the DataGridView
this.dbif.GetProcedure(this.procList.ElementAt(selectedIndex).PrimaryKey, ref this.dgvDataTable);

DataRow[] rows = this.dgvDataTable.Select();
//Object dgvDataSource = dgv.DataSource;
//dgv.DataSource = null;

foreach (DataRow dataRow in rows)
{
    DataGridViewRow dgvRow = new DataGridViewRow();
    dgvRow.CreateCells(dgv);
    dgvRow.Cells[idxSection].Value = dataRow.Field<string>(0);
    dgvRow.Cells[idxIndent].Value = dataRow.Field<byte>(1);
    dgvRow.Cells[idxContent].Value = dataRow.Field<string>(3);
    dgvRow.Cells[idxSummary].Value = dataRow.Field<UInt32>(4) != 0;
    dgvRow.Cells[idxRole].Value = dataRow.Field<string>(5);
    dgvRow.Cells[idxAuthor].Value = dataRow.Field<string>(6) + dataRow.Field<string>(7);
    dgvRow.Cells[idxLastUpdate].Value = dataRow.Field<DateTime>(8).ToString();
    dgv.Rows.Add(dgvRow);
}

//dgv.DataSource = dgvDataSource;

This is how my enumerations are defined:

public enum SectionType
{
    ESJP_SECTION_HEADER = 1,        // start with 1 for database compatibility
    ESJP_SECTION_FOOTER,
    ESJP_SECTION_BODY
}

public enum RoleType
{
    ESJP_ROLE_NONE = 1,             // start with 1 for database compatibility
    ESJP_ROLE_TEST_ENG,
    ESJP_ROLE_FEATURE_LEAD,
    ESJP_ROLE_TEAM_LEAD
}

Aucun commentaire:

Enregistrer un commentaire