C# Allowing only one row to be selected in checkbox coloum in each datagridview on a form

Steve Williams 0 Reputation points
2023-11-29T16:22:26.6633333+00:00

Hi I'm still very new to C# and struggling with the following issue with DataGridViews in my windows forms app.

I have a form that has two combo boxes (combo1 & combo2) and two datagridview (dgv1 & dgv2) controls on it.

Both combo boxes have a list of tables from a database in them: combo1 has a list from "SrcDB" and comb2 has a list from "StagingDB".

The SelectedIndexChanged event of each combo box triggers the population of the relevant DataGridView e.g. Selecting "TableA" from combo1 will populate dgv1 with the column names from TableA in the SrcDB database.

The same goes for combo2, where it populates the dgv2 with a list of the columns from the selected table in the StagingDB.

I have added a checkbox column to each DataGridView.

What I want to do is limit each datagridview to only allow one checkbox to be selected at once.

However, setting the VirtualMode to True for each checkbox then only allow one checkbox across both datagridview controls to be selected, which is not what I want.

So I don't know how to do this correctly. This is kind of what I am after:

User's image

What I am trying to do is build a field mapper, whereby I can map a field in dgv1 to a field in dgv2 via a button click. For recall purposes in my app (pick up where the user left off), I'd be looking to populate a table in the StagingDB containing the list of mappings

Example below would be the result from the grid above:

SrcTable SrcField StagingTable StagingField
BESPOKE_TABLE Rand_FirstName CONTACT_SOURCE KFirstName

After a mapping is done between two columns, I'd then look to remove the items already mapped from the grids, and keep going until there are no fields left to map in either grid.

I can then use the table above to dynamically build a SQL statement to do insert the data into the staging table from the source table.

I can achieve this by leaving the VirtualMode turned off for the datagrids and deliberately only checking one checkbox in each grid. But that then means it can be broken by selecting more than one row in each grid and causing issues with the code.

Any help with this will be much appreciated.

Many thanks

Steve

Developer technologies Windows Forms
Developer technologies C#
{count} votes

1 answer

Sort by: Most helpful
  1. Karen Payne MVP 35,586 Reputation points Volunteer Moderator
    2023-11-29T17:54:31.53+00:00

    Below may or may not help as displayed as I took it from an old VB.NET project done over 10 years ago, ran it and worked, allows only one row to be checked. Next ran it through a converter what may or may not have gotten everything perfect.

    public class Form1
    {
    
    	private void InitializeInstanceData()
    	{
    		bsAnswers = new BindingSource();
    	}
    
    	private BindingSource bsAnswers;
    
    	private void Form1_Load(object sender, System.EventArgs e)
    	{
    
    		DataOperations ops = new DataOperations();
    
    		bsAnswers.DataSource = ops.ReadMockedData; // brings back a DataTable
    		DataGridView1.DataSource = bsAnswers;
    		DataGridView1.Columns("SelectionColumn").Width = 25; // the checkbox column
    		DataGridView1.Columns("SelectionColumn").HeaderText = "";
    		DataGridView1.Columns("OptionName").HeaderText = "";
    	}
    
    	private void DataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
    	{
    
    		var value = Convert.ToBoolean(DataGridView1.Rows(e.RowIndex).Cells("SelectionColumn").Value);
    
    		if (value)
    		{
    			int index = e.RowIndex;
    			for (int row = 0; row < DataGridView1.Rows.Count; row++)
    			{
    				if (row != index)
    				{
    					DataGridView1.Rows(row).Cells("SelectionColumn").Value = false;
    				}
    			}
    		}
    		else
    		{
    			DataGridView1.Rows(e.RowIndex).Cells("SelectionColumn").Value = true;
    			int index = e.RowIndex;
    			for (int row = 0; row < DataGridView1.Rows.Count; row++)
    			{
    				if (row != index)
    				{
    					DataGridView1.Rows(row).Cells("SelectionColumn").Value = false;
    				}
    			}
    		}
    
    		// Force cell painting
    		DataGridView1.CurrentCell = DataGridView1[0, e.RowIndex];
    
    	}
    	private void DataGridView1SelectAll_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    	{
    		if (DataGridView1.CurrentCell is DataGridViewCheckBoxCell)
    		{
    			DataGridView1.EndEdit();
    		}
    	}
    }
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.