DataGridViewComboBoxColumn.DataSource change problem1 - c#

I have a DataGridView with a DataGridViewComboBoxColumn in the first column that is bind whith a List<MyClass> and a DisplayMember="name" (I dont set the valeumember because i want to get myclass when I accesse to value). The second column is a DataGridViewComboBoxColumn too. It will be bound to some List<String> based on the first DataGridViewComboBoxColumn selectedValue.
All this work just fine, the problem starts when I change the first DataGridViewComboBoxColumn.DataSource. When I add a new Myclass to the datasource it works, but if I select the class I will get an error:
System.ArgumentException: DataGridViewComboBoxCell value is not valid
Code:
//Set columns to Datagridview
DataGridViewImageColumn btnEdit = new DataGridViewImageColumn();
Image gear = (System.Drawing.Image)Properties.Resources.gear;
btnEdit.Image = gear;
datagridview.Columns.Add(btnEdit);
//Table
DataGridViewComboBoxColumn cbTable = new DataGridViewComboBoxColumn();
cbTable.HeaderText = "Table";
cbTable.Name = "Table";
cbTable.DisplayMember = "NameToShow";
//tableDataSource = cbTable.DataSource;
//cbTable.DataSource = moduleClone.SqlQuery.Tables;
datagridview.Columns.Add(cbTable);
//...
//...
//...
//Load data
((DataGridViewComboBoxColumn)datagridview.Columns[1]).DataSource = (List<Table>)moduleClone.SqlQuery.Tables;
//Work just fine
//...
//...
//...
//Now if i reload de data
datagridview.Rows.Clear();
((DataGridViewComboBoxColumn)datagridview.Columns[1]).DataSource = (List<Table>)moduleClone.SqlQuery.Tables;
//This give me one message box with the exception several times when drawing the gridview.

Ok, I found a solution that works for me.
Instead use DataGridViewComboBoxColumn.DataSource, I directly change DataGridViewComboBoxColumn.Items. Has a probleme because you cant change DataGridViewComboBoxColumn.Items if DataGridViewComboBoxColumn.DataSource is set. So I define DataGridViewComboBoxColumn.DataSource = null before edit DataGridViewComboBoxColumn.Itens.
Code:
//Set columns to Datagridview
DataGridViewImageColumn btnEdit = new DataGridViewImageColumn();
Image gear = (System.Drawing.Image)Properties.Resources.gear;
btnEdit.Image = gear;
datagridview.Columns.Add(btnEdit);
//Table
DataGridViewComboBoxColumn cbTable = new DataGridViewComboBoxColumn();
cbTable.HeaderText = "Table";
cbTable.Name = "Table";
cbTable.DisplayMember = "NameToShow";
datagridview.Columns.Add(cbTable);
//...
//...
//...
//Load data
((DataGridViewComboBoxColumn)datagridview.Columns[1]).Itens = (List<Table>)moduleClone.SqlQuery.Tables;
//Work just fine
//...
//...
//...
//Now I reload de data
datagridview.Rows.Clear();
((DataGridViewComboBoxColumn)datagridview.Columns[1]).DataSource = null;
((DataGridViewComboBoxColumn)datagridview.Columns[1]).Items.clear();
((DataGridViewComboBoxColumn)datagridview.Columns[1]).Items= (List<Table>)moduleClone.SqlQuery.Tables;

Related

How to change DataGridViewComboBoxColumn back to DataGridViewColumn?

I setup my DataGridViewComboBoxColumn like this:
DataGridViewComboBoxColumn partStatusCol = new DataGridViewComboBoxColumn();
partStatusCol.DataSource = PostgreSQLConnection.AddDataSet(query.ListPartStatusValue());
partStatusCol.DisplayMember = "Value_Status";
partStatusCol.DataPropertyName = "Part_Status";
partStatusCol.Name = "Part_Status";
if (dataGridView1.Columns.Contains("Part_Status"))
{
int index = dataGridView1.Columns["Part_Status"].Index;
dataGridView1.Columns.Remove("Part_Status");
dataGridView1.Columns.Insert(index, partStatusCol);
}
And now i want to reset this stuff and change it back to the ordinary DataGridViewColumn.
I tried to reset the DataSet but it doesn't work.

DatagridView with variable number of columns

I want to create a datagridview in C# (winform) with a variable number of columns. I have done this
dataGridView2 = _dm.CreateGrid();
where CreateGrid() is the following method:
public DataGridView CreateGrid()
{
DataGridView dtgr = new DataGridView();
using (DbEntities db = new DbEntities())
{
foreach (Resource r in db.Resources)
{
DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
col.ValueType = typeof(string);
col.Name = r.Description;
col.HeaderText = r.Description;
col.DataPropertyName = r.Description;
dtgr.Columns.Add(col);
}
}
return dtgr;
}
Description is of type string. I don't see the datagridview in my winform. Where is the problem ?
I think DataGridViewTextBoxColumn is causing the problem. Try using DataGridViewColumn instead. Hope that helps.
You need add your DataGridView to controls of the Form
dataGridView2 = _dm.CreateGrid();
this.Controls.Add(dataGridView2);
Why you create columns manually. DataGridView will generate columns automatically based on the columns/fields of the datasource, if you set AutoGenerateColumns = true
From MSDN DataGridView.AutoGenerateColumns Property

how to add a combo box in a datagrid view for only one cell dynamically

I am reading an xml file using dataset and then i am creating a datagridview and assigning the table from dataset to datagridview.datasource dynamically.
The problem i am facing here is, i want to add a combobox for one cell in datagridview.
Below is my code :
datagridview1.AllowUserToAddRows = false;
datagridview1.AllowUserToDeleteRows = false;
datagridview1.RowHeadersVisible = false;
datagridview1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
datagridview1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
datagridview1.DataMember = "";
datagridview1.DataSource = my_dataTable;
datagridview1.Columns["first name"].ReadOnly = true;
datagridview1.Columns["Second name"].Visible = false;
datagridview1.Columns["place"].Visible = false;
datagridview1.Columns["address"].Visible = false;
string[] datasource = { "add1", "add2" };
DataGridViewComboBoxCell combo = new DataGridViewComboBoxCell();
combo.DataSource = datasource;
datagridview1.Rows[2].Cells[2] = combo;
It is giving me datagridviewcomboboxcell value is not valid error.If i give some value then it runs well but not able to see the combobox in datagridview.
You can use the DataSource to feed to Items, but using a simple string array will not work.
Instead you can convert the array to a List<string> :
string[] datasource = { "add1", "add2" };
DataGridViewComboBoxCell combo = new DataGridViewComboBoxCell();
combo.DataSource = datasource.ToList();
DGV.Rows[2].Cells[2] = combo;
To set a value you can use..
combo.Value = combo.Items[0];
..after having set the cell.
For better control, especially for having spearate Display- and ValueMembers you can switch to a Dictionary or use a List<someClass>..

How to set a DataGridView column to a DataGridViewComboBoxColumn?

Here is my code:
DataSet data = new DataSet();
data.ReadXml("data.xml");
DataGridView grid = new DataGridView();
var genreCboBoxItems = data.Tables[0].AsEnumerable().Select(genre => genre.Field<string>("genre")).Distinct().ToArray();
// TODO: Make is so the 'genre' column in grid is a combo box?
grid.DataSource = data.Tables[0];
grid.Dock = DockStyle.Fill;
this.Controls.Add(grid);
*edit: genreCboBoxItems
Try this: (not tested)
var column = new DataGridViewComboBoxColumn();
column.DataSource = data.Tables[0].AsEnumerable().
Select(genre => new { genre = genre.Field<string>("genre") }).Distinct();
column.DataPropertyName = "genre";
column.DisplayMember = "genre";
column.ValueMember = "genre";
grid.DataSource = data.Tables[0];
// Instead of the below line, You could use grid.Columns["genre"].Visible = false;
grid.Columns.Remove("genre");
grid.Columns.Add(column);
This might help you cast DataGridViewColumn to DataGridViewComboBox.
First create DataGridViewComboBoxColumn using designer with proper name. Then say you have a list of String list and other string values to bind to that datagridview then use this code:
Below code will bind a list to two DataGridViewTextBoxCell and a DataGridViewComboBoxCell. Note AllCriterias is a list with two string values and a list of string. DGVEligibilityCriteria is the grid name.
for (int i = 0; i < AllCriterias.Count; i++)
{
DataGridViewTextBoxCell Cmb1 = (DataGridViewTextBoxCell)DGVEligibilityCriteria.Rows[i].Cells[0];
Cmb1.Value = AllCriterias[i].Name;
DataGridViewTextBoxCell Cmb2 = (DataGridViewTextBoxCell)DGVEligibilityCriteria.Rows[i].Cells[1];
Cmb2.Value = AllCriterias[i].Type;
DataGridViewComboBoxCell Cmb = (DataGridViewComboBoxCell)DGVEligibilityCriteria.Rows[i].Cells[2];
foreach (var filtervalue in AllCriterias[i].FilterValues)
{
Cmb.Items.Add(filtervalue);
}
}
Need to display the fist index as default by setting selectindex property.
Use this code : Here "filterValues" is the name of the DataGridViewComboBoxCell which u created in the datagridview designer.
foreach (DataGridViewRow row in DGVEligibilityCriteria.Rows)
{
row.Cells["filterValues"].Value = (row.Cells["filterValues"] as DataGridViewComboBoxCell).Items[0];
}

I am having some trouble with adding checkbox column in a my datagridview

I have a datagridview on my page, the datasource of which keeps changing based on records retrieved with pair of values from 2 combo-boxes,
I need to add a checkbox column to my datagrid, which has no databinding with any column from my database table, i am using this code
public void RefreshDataGrid(string query)
{
Buisness_logic bl = new Buisness_logic();
dataGridView1.DataSource = bl.GetDataTable(query);
SetUpDataGridView();
dataGridView1.ClearSelection();
}
public void SetUpDataGridView()
{
DataGridViewCellStyle style = dataGridView1.ColumnHeadersDefaultCellStyle;
style.BackColor = Color.White;
style.ForeColor = Color.Black;
dataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically;
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
dataGridView1.RowHeadersVisible = false;
dataGridView1.Columns[0].HeaderText = "Sr.No";
dataGridView1.Columns[0].Width = 50;
dataGridView1.Columns[1].HeaderText = "Rate";
dataGridView1.Columns[1].Width = 70;
dataGridView1.Columns[2].HeaderText = "Amount";
dataGridView1.Columns[2].Width = 100;
dataGridView1.Columns[3].HeaderText = "Mode";
dataGridView1.Columns[3].Width = 60;
dataGridView1.Columns[4].HeaderText = "Support";
dataGridView1.Columns[4].Width = 80;
dataGridView1.Columns[5].HeaderText = "Team1";
dataGridView1.Columns[5].Width = 100;
dataGridView1.Columns[6].HeaderText = "Team2";
dataGridView1.Columns[6].Width = 100;
dataGridView1.Columns[7].HeaderText = "Team3";
dataGridView1.Columns[7].Width = 100;
DataGridViewCheckBoxColumn column3 = new DataGridViewCheckBoxColumn();
column3.Name = "Column3";
column3.HeaderText = "IsCheck";
column3.ReadOnly = false;
dataGridView1.Columns.Add(column3);
}
It datagridview is good when tge form loads the first time, but when i change the value of the combo-boxes and the datasource changes, the columns get messed up, and a no. of checkbox columns get added and that ruins my form,
here is the code i used to retrieve the records from table
Combo_pair pr1 = combo_match_code.SelectedItem as Combo_pair;
int match_code_f1 = Convert.ToInt32(pr1.Text);
Combo_pair pair = combo_name.SelectedItem as Combo_pair;
int userid_f1 = Convert.ToInt32(pair.Value);
string query = "Select int_sr_no,double_rate,double_amount,txt_mode,txt_support,double_team1,double_team2,double_team3 from match_transaction where int_match_code='" + match_code_f1 + "' AND int_user_id='" + userid_f1 + "' AND is_deleted=0";
RefreshDataGrid(query);
this is the image when the form loads for the first time
and this is the image after i change the combo box values a few times
*(sorry, having trouble with images)
i really need some help with these, thanxx
Before the answer I'm just going to restate the problem in steps (so that my solution hopefully makes more sense):
You have a databound DataGridView where you want to change details of columns
When you want refresh the data in the grid (your search criteria change) your changes to the columns are overwritten
To fix this you update date grid datasource and remake all the changes
This has the side effect that an unbound checkbox column you add is being added multiple times
So the problem in a nutshell is how to keep the changes to columns while also only having the one column?
The trick here is the DataGridView's AutoGenerateColumns property.
For sake of argument let is say that you first setup your grid during the form load - if not then you might need a boolean field to store if you have previously setup the grid.
public Form1()
{
InitializeComponent();
// So this is the first time we call your refresh grid with some default string query
RefreshDataGrid(query);
// Now one time only we call SetUpDataGridView()
SetUpDataGridView();
// Now once we have done that we set AutoGenerateColumns to false
dataGridView1.AutoGenerateColumns = false;
}
public void RefreshDataGrid(string query)
{
Buisness_logic bl = new Buisness_logic();
dataGridView1.DataSource = bl.GetDataTable(query);
// We no longer need to call SetUpDataGridView()
// SetUpDataGridView();
dataGridView1.ClearSelection();
}
Your SetUpDataGridView() method is pretty much identical:
public void SetUpDataGridView()
{
DataGridViewCellStyle style = dataGridView1.ColumnHeadersDefaultCellStyle;
style.BackColor = Color.White;
style.ForeColor = Color.Black;
dataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically;
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
dataGridView1.RowHeadersVisible = false;
dataGridView1.Columns[0].HeaderText = "Sr.No";
dataGridView1.Columns[0].Width = 50;
// And so on for all the columns...
dataGridView1.Columns[7].Width = 100;
DataGridViewCheckBoxColumn column3 = new DataGridViewCheckBoxColumn();
column3.Name = "Column3";
column3.HeaderText = "IsCheck";
column3.ReadOnly = false;
dataGridView1.Columns.Add(column3);
}
So now when the combboxes containing the query information change you can call RefreshDataGrid() but it will only update the data, not change your custom settings.
One suggestion for the RefreshDataGrid() method is to add a line like so:
public void RefreshDataGrid(string query)
{
Buisness_logic bl = new Buisness_logic();
// This is the new line
dataGridView1.DataSource = typeof(List<>);
dataGridView1.DataSource = bl.GetDataTable(query);
// We no longer need to call SetUpDataGridView()
// SetUpDataGridView();
dataGridView1.ClearSelection();
}
This can reduce flicker as column widths change and also is often necessary to make changing the DataSource show at all.
You need to setup the gridview only once.
A good place to do this is after InitializeComponent().
Since this is a fixed column, you could also add it through the designer (Edit Columns).
That way the code would get add to InitializeComponent().
InitializeComponent() is usually called in the constructor of your form.
At present you are adding this line
dataGridView1.Columns.Add(column3);
Will cause the checkbox column to be added several times.

Categories

Resources