Background
I have a datagridview that is bound to a dataset. That dataset stores data from a sql db that is obtained using a SqlCommandBuilder. When the dataset is updated the db is updated too.
This works fine.
However I would like one of the columns to contain a combobox.
To do this I have added a DataGridViewComboBoxColumn and hidden the original column. I've then then tried to add extra items to the combobox and then bound the dataset.
My Code
dataGridView1.DataSource = JoblistDataSet.Tables["Joblist"]; //bind ds to dgv
dataGridView1.Columns["Status"].Visible = false; //hide original column
DataGridViewComboBoxColumn Status = new DataGridViewComboBoxColumn();
//setup combobox
Status.Items.Insert(0, "Select Status");//add extra items
Status.DataSource = JoblistDataSet.Tables["Joblist"];//add original item from ds
Status.HeaderText = #"Status ";
Status.DisplayMember = "Status";
Status.DropDownWidth = 78;
Status.DataPropertyName = "Status";
Status.DisplayIndex = 7;
//add combobox
dataGridView1.Columns.Add(Status);
dataGridView1.Refresh();
What i'm Trying to Achieve
I would like a combobox on one of the datagridview columns. In that combobox, the first item should contain (and be displayed) the row's actual value, the other items should contain the other available items.
Question
However, this doesn't seem to work. All I'm getting is the actual rows actual value. Am i going the wrong way about it. Is there a better way to do this?
Related
My end goal is to populate a DataGrid with data retrieved from a database at runtime. My methodology is to pull all the columns from that database first and then pull the corresponding data for each column for each row as below:
ReadOnlyCollection<Field> tablefields = {//has the fields populated from the database};
//adding all the columns to the data table
var datatable = new DataTable("mytable");
foreach (var field in tablefields)
{ datatable.Columns.Add(field.Name, wFieldType); }
//Then add the rows
while (cursor.MoveNext())
{
var tableRow = datatable.NewRow();
var row = cursor.Current;
for(var i = 0; i < tablefields.Count; i++)//add the values for each field to the data table.
{
tableRow[i] = row[i] ?? DBNull.Value;
}
datatable.Rows.Add(tableRow);
}
My problem however is that some of the columns that I am pulling have to be in the form of a DataGridComboBoxColumn since they have preset values in a dropdown list in the database. The best case scenario would have been that as I pull the columns into my dataTable one by one, I would detect the ones that have preset values and make those oftype DataGridComboBoxColumn before adding them to the dataTable. I obviously can't do that because you cannot have a combobox on a dataTable. My next option is to use the dataGrid to load the columns and the data from the database at runtime.
I am able to add the columns with a combobox as shown in the code below but I cannot figure out how to get my data from the database into the dataGrid containing the pre-loaded columns.
DataGridComboBoxColumn cb = new DataGridComboBoxColumn();
cb.ItemsSource = new List(){to be populated later}
cb.Header = field.Name;
MyDataGrid.Columns.Add(cb);
The code above was used as a sample to test the DataGridComboBoxColumn and sure enough I was able to see the datagrid with the comboboxes. I just can't figure out how to get my database data into the table. I would appreciate any ideas.
PS: I cannot use datagridview because of the api that I am working with so I am limited to datagrid.
You should set the SelectedItemBinding to a binding to a column in your DataTable that contains the value in the ItemsSource to be selected:
cb.SelectedItemBinding = new Binding("AColumnInYourDataTable");
If you set the ItemsSource to a List<T> where T is a complex type, you should instead set the SelectedValueBinding and SelectedValuePath and DisplayMemberPath properties:
cb.SelectedValueBinding = new Binding("AColumnInYourDataTable");
cb.SelectedValuePath = "NameOfThePropertyOfTThatHoldsTheValue";
cb.DisplayMemberPath = "NameOfAPropertyOfTThatHoldsTheDisplayName";
I am adding columns to datagrid and displaying in my application
// Create Datagrid
Mytable = new DataTable("My Table");
// Add Columns
Mytable.Columns.Add(My_Localization.Cultures.Resources.UserId);
Mytable.Columns.Add(My_Localization.Cultures.Resources.Name);
// Fill data
DataRow dr = Mytable.NewRow();
dr[0] = UserId;
dr[1] = Name;
// Add itemsource
DetailsDlg.ItemsSource = Mytable.AsDataView();
Now is it possible to change the columns names when my localization languages changes on the fly? Since columns are added in the code, I am not able to change the column headers. If I put the columns in wpf, then I am not able to add the data before assigning the itemsource. How do I solve this?
Assuming you are binding your datagrid from your code behind and you are not using MVVM.
You can always change your desire column in your code behind, like this:
DetailsDlg.Columns[0].Header = "New column name";
I know you can use the BindingSource object with a DataGridView.
Is it possible to have a combo box in one of the columns and still take advantage of the BindingSource?
Yes, it is - take a look at ComboBox with DataGridView in C#:
Using ComboBox with DataGridView is not that complex anymore but it’s almost mandatory while doing some data driven software development.
I have created a DataGridView like this one. Now, I want to show “Month” and “Item” instead of “MonthID” and “ItemID” in DataGridView.
Essentially what the article describes is binding the comboboxes with a separate binding source - in this case, a validation table, where MonthID and MonthName are stored, and the month name is displayed based on the id from the original data.
Here he sets up the Month data source, selecting from a month table, and then creates a BindingSource from the returned data.
//Month Data Source
string selectQueryStringMonth = "SELECT MonthID,MonthText FROM Table_Month";
SqlDataAdapter sqlDataAdapterMonth = new SqlDataAdapter(selectQueryStringMonth, sqlConnection);
SqlCommandBuilder sqlCommandBuilderMonth = new SqlCommandBuilder(sqlDataAdapterMonth);
DataTable dataTableMonth= new DataTable();
sqlDataAdapterMonth.Fill(dataTableMonth);
BindingSource bindingSourceMonth = new BindingSource();
bindingSourceMonth.DataSource = dataTableMonth;
Then he adds the month ComboBoxColumn to the DataGridView, using the DataSource as the BindingSource created above:
//Adding Month Combo
DataGridViewComboBoxColumn ColumnMonth = new DataGridViewComboBoxColumn();
ColumnMonth.DataPropertyName = "MonthID";
ColumnMonth.HeaderText = "Month";
ColumnMonth.Width = 120;
ColumnMonth.DataSource = bindingSourceMonth;
ColumnMonth.ValueMember = "MonthID";
ColumnMonth.DisplayMember = "MonthText";
dataGridViewComboTrial.Columns.Add(ColumnMonth);
And then finally, he binds the DataGridView to the original data.
I have a datagridview which has multiple text columns and a single comboboxcolumn. I need to specify a datasource for the iems of the comboboxcolumn and another datasource for the other text columns. I have tried the following sample code but it does not work.
dgv1.DataSource = DataSet1.Tables[0];
string[] managerList = Array.ConvertAll(DataSet2.Select(), row => (string)row[0]);
comboboxcolumn1.DataSource = managerList;
The managerList array has the entries that are to be populated into the combobox but they never show up.
Is that so that I can not have a separate datasource for a comboboxcolumn and its parent datagridview?
Thanks in advance.
I have checked with the following code and it works fine
string[] arr = "This Should Get Displayed".Split(); //managerList in your case
dataGridView1.DataSource = MyData(false);
(dataGridView1.Columns["Column1"] as DataGridViewComboBoxColumn).DataSource = new BindingSource(arr, null); // Bind to the column of grid
Can you try assigning it as referencing it as a column of your datagridview.
This displays the text split on space in my combobox.
When you are using string array no need to specify Display and Value member for the column
EDIT
If you have a DataTable you can also do it in this fashion
(dataGridView1.Columns["Column1"] as DataGridViewComboBoxColumn).DataSource= datatable;
(dataGridView1.Columns["Column1"] as DataGridViewComboBoxColumn).DisplayMember="columnname";
(dataGridView1.Columns["Column1"] as DataGridViewComboBoxColumn).ValueMember="columnname";
I have a DataTable as a data source of a GridView. I'm adding a combo box the the GridView .
I'd like to be able to add a column to the DataTable that would automatically update with the value the user selects in the GridView. Can anyone help?
and the answer is...
DataTable myTable = getYourDataByMagic();
DataGridViewComboBoxColumn box = new DataGridViewComboBoxColumn();
BindingSource bs = new BindingSource();
bs.add("choice one");
bs.add("choice two");
box.HeaderText = "My Choice";
box.Name = "select";
box.DataSource = bs;
box.DataPropertyName = "select";
myTable.Columns.Add(new DataColumn("select"));
this.dataGridView1.Columns.Add(box);
this.dataGridView1.DataSource = myTable;
now, your "myTable" will update with the values selected in the combobox
I'd put two grids side by side one containing all info and one that just had the blank column. I would update the datatable with the grid that contained the one column. This would be update based on selected index of the previous grid. First thing to come to mind.