none
DataGridView Unbound Column

    Question

  • I have an unbound column with a combobox in my dataGridView. I was not able to get a combobox bound to the SQL Server table to allow for the item collection.  I was able to use the item collection in an unbound column with a combobox in the dataGridView.

    Now, the row is not deleted when I click the binding Navigator delete button. Also, the binding Navigator Move Next Item and Move Previous Item do not work correctly.

    Could these problems be caused by the use of the unbound column with a combobox in the dataGridView?

    Thanks,

    Isom

    Tuesday, December 05, 2017 8:58 PM

Answers

  • Your unbound column can not be setup to work directly with data retrieved from a database table. If I wanted an unbound column it's only there from when you set it up until the app closes.

    If I have from the database

    And want to add a unbound column for say gender I would add the column in the designer and populate in code e.g.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace TableAdapterWindowsForms
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void customerBindingNavigatorSaveItem_Click(object sender, EventArgs e)
            {
                this.Validate();
                this.customerBindingSource.EndEdit();
                this.tableAdapterManager.UpdateAll(this.customersDataSet);
    
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                // TODO: This line of code loads data into the 'customersDataSet.Customer' table. 
                // You can move, or remove it, as needed.
                this.customerTableAdapter.Fill(this.customersDataSet.Customer);
                // TODO: This line of code loads data into the 'customersDataSet.Customer' table. 
                // You can move, or remove it, as needed.
                this.customerTableAdapter.Fill(this.customersDataSet.Customer);
                GenderColumn.DataSource = new string[] {"Female","Male","Other" };
                GenderColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
    
            }
    
            private void customerBindingNavigatorSaveItem_Click_1(object sender, EventArgs e)
            {
                this.Validate();
                this.customerBindingSource.EndEdit();
                this.tableAdapterManager.UpdateAll(this.customersDataSet);
    
            }
    
            private void currentButton_Click(object sender, EventArgs e)
            {
                var row = ((DataRowView)customerBindingSource.Current).Row;
    
                if (customerBindingSource.Current != null)
                {
                    var gender = Convert.ToString(
                        customerDataGridView.Rows[customerBindingSource.Position].Cells["GenderColumn"].Value);
    
                    if (!string.IsNullOrWhiteSpace(gender))
                    {
                        MessageBox.Show($"{row.Field<string>("ContactName")} is {gender}");
                    }
                    else
                    {
                        MessageBox.Show($"{row.Field<string>("ContactName")} gender not selected");
                    }                
                }
            }
        }
    }

    How about instead I did

    Setup a unbound DataGridViewComboBox column

    I then drop on Customer table as a DataGridView with the above setup (I got ahead of myself)

    Drag Genders to the form as details, delete them which keeps the components in the tray (we don't need all the components like the gender BindingSource but let's keep going, you can clean up later)

    At run time

    Backing code the magic is in setting the DataPropertyName for GenderNameColumn which adheres that column to data loaded from the customer data which is our bound data. 

    using System;
    using System.Data;
    using System.Windows.Forms;
    
    namespace TableAdapterWindowsForms1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void customerBindingNavigatorSaveItem_Click(object sender, EventArgs e)
            {
                this.Validate();
                this.customerBindingSource.EndEdit();
                this.tableAdapterManager.UpdateAll(this.customerDataSet);
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                // TODO: This line of code loads data into the 'customerDataSet.Genders' table. 
                // You can move, or remove it, as needed.
                this.gendersTableAdapter.Fill(this.customerDataSet.Genders);
                // TODO: This line of code loads data into the 'customerDataSet.Customer' 
                // table. You can move, or remove it, as needed.
                this.customerTableAdapter.Fill(this.customerDataSet.Customer);
                // TODO: This line of code loads data into the 'customerDataSet.Customer' table. 
                // You can move, or remove it, as needed.
                this.customerTableAdapter.Fill(this.customerDataSet.Customer);
    
    
                // Begin Karen's code
                GenderNameColumn.DisplayMember = "GenderType";
                GenderNameColumn.ValueMember = "id";
                GenderNameColumn.DataPropertyName = "GenderIdentifier";
                GenderNameColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
                GenderNameColumn.DataSource = customerDataSet.Genders;
                // End Karen's code
    
            }
    
            private void customerBindingNavigatorSaveItem_Click_1(object sender, EventArgs e)
            {
                this.Validate();
                this.customerBindingSource.EndEdit();
                this.tableAdapterManager.UpdateAll(this.customerDataSet);
    
            }
            /// <summary>
            /// Crude way to show when a change to the ComboBox GenderNameColumn happens 
            /// we can see it changed the id pointing to gender
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void button1_Click(object sender, EventArgs e)
            {
                var row = ((DataRowView)customerBindingSource.Current).Row;
                Console.WriteLine(string.Join(",",row.ItemArray));
            }
        }
    }

    See the values

    That should do it.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites



    Friday, December 08, 2017 1:40 AM

All replies

  • Hi Isom,

    Sorry that I can not understand what you mean about "unbound column", could you please provide some code to describe it?

    Hope you can provide more details for your question.

    Regards,

    Stanly


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, December 06, 2017 9:00 AM
    Moderator
  • Unbound means the column in the data grid view is not associated with a column in the SQL Server table. The unbound column is a combo box control.
    Wednesday, December 06, 2017 3:49 PM
  • Hi,

    Just as I said above, maybe you should provide some code or a simple demo for more details, I can not think of the reason just by my guess.

    Regards,

    Stanly


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, December 07, 2017 7:12 AM
    Moderator
  • I have removed the combo box from the data grid view control because I have not been able to access the items collection and have not been able to update the SQL Server table once the user selects an item in the collection.

    The problem of not being able to delete a row in the data grid view and navigate to other rows were not caused by the use of the combo box in the data grid view. I am still not able to delete a row using the Delete button on the binding navigator but I can navigate to other rows without a problem.

    Thanks for your inquiry.

    Thursday, December 07, 2017 3:00 PM
  • Your unbound column can not be setup to work directly with data retrieved from a database table. If I wanted an unbound column it's only there from when you set it up until the app closes.

    If I have from the database

    And want to add a unbound column for say gender I would add the column in the designer and populate in code e.g.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace TableAdapterWindowsForms
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void customerBindingNavigatorSaveItem_Click(object sender, EventArgs e)
            {
                this.Validate();
                this.customerBindingSource.EndEdit();
                this.tableAdapterManager.UpdateAll(this.customersDataSet);
    
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                // TODO: This line of code loads data into the 'customersDataSet.Customer' table. 
                // You can move, or remove it, as needed.
                this.customerTableAdapter.Fill(this.customersDataSet.Customer);
                // TODO: This line of code loads data into the 'customersDataSet.Customer' table. 
                // You can move, or remove it, as needed.
                this.customerTableAdapter.Fill(this.customersDataSet.Customer);
                GenderColumn.DataSource = new string[] {"Female","Male","Other" };
                GenderColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
    
            }
    
            private void customerBindingNavigatorSaveItem_Click_1(object sender, EventArgs e)
            {
                this.Validate();
                this.customerBindingSource.EndEdit();
                this.tableAdapterManager.UpdateAll(this.customersDataSet);
    
            }
    
            private void currentButton_Click(object sender, EventArgs e)
            {
                var row = ((DataRowView)customerBindingSource.Current).Row;
    
                if (customerBindingSource.Current != null)
                {
                    var gender = Convert.ToString(
                        customerDataGridView.Rows[customerBindingSource.Position].Cells["GenderColumn"].Value);
    
                    if (!string.IsNullOrWhiteSpace(gender))
                    {
                        MessageBox.Show($"{row.Field<string>("ContactName")} is {gender}");
                    }
                    else
                    {
                        MessageBox.Show($"{row.Field<string>("ContactName")} gender not selected");
                    }                
                }
            }
        }
    }

    How about instead I did

    Setup a unbound DataGridViewComboBox column

    I then drop on Customer table as a DataGridView with the above setup (I got ahead of myself)

    Drag Genders to the form as details, delete them which keeps the components in the tray (we don't need all the components like the gender BindingSource but let's keep going, you can clean up later)

    At run time

    Backing code the magic is in setting the DataPropertyName for GenderNameColumn which adheres that column to data loaded from the customer data which is our bound data. 

    using System;
    using System.Data;
    using System.Windows.Forms;
    
    namespace TableAdapterWindowsForms1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void customerBindingNavigatorSaveItem_Click(object sender, EventArgs e)
            {
                this.Validate();
                this.customerBindingSource.EndEdit();
                this.tableAdapterManager.UpdateAll(this.customerDataSet);
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                // TODO: This line of code loads data into the 'customerDataSet.Genders' table. 
                // You can move, or remove it, as needed.
                this.gendersTableAdapter.Fill(this.customerDataSet.Genders);
                // TODO: This line of code loads data into the 'customerDataSet.Customer' 
                // table. You can move, or remove it, as needed.
                this.customerTableAdapter.Fill(this.customerDataSet.Customer);
                // TODO: This line of code loads data into the 'customerDataSet.Customer' table. 
                // You can move, or remove it, as needed.
                this.customerTableAdapter.Fill(this.customerDataSet.Customer);
    
    
                // Begin Karen's code
                GenderNameColumn.DisplayMember = "GenderType";
                GenderNameColumn.ValueMember = "id";
                GenderNameColumn.DataPropertyName = "GenderIdentifier";
                GenderNameColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
                GenderNameColumn.DataSource = customerDataSet.Genders;
                // End Karen's code
    
            }
    
            private void customerBindingNavigatorSaveItem_Click_1(object sender, EventArgs e)
            {
                this.Validate();
                this.customerBindingSource.EndEdit();
                this.tableAdapterManager.UpdateAll(this.customerDataSet);
    
            }
            /// <summary>
            /// Crude way to show when a change to the ComboBox GenderNameColumn happens 
            /// we can see it changed the id pointing to gender
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void button1_Click(object sender, EventArgs e)
            {
                var row = ((DataRowView)customerBindingSource.Current).Row;
                Console.WriteLine(string.Join(",",row.ItemArray));
            }
        }
    }

    See the values

    That should do it.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites



    Friday, December 08, 2017 1:40 AM
  • Thanks for all of the code. I may go back and modify the application with your example because I could not get the combo box to work the way I was doing it. Thanks again for the thorough example.
    Monday, December 11, 2017 9:47 PM