I am using a VS 2012 Windows Forms datagridview control. The datasource for the grid is a JObject but I have one predefined column that is supposed to display data from one of the datasource cells, which is also a JObject. After the datasource is assigned to the grid, I loop through the rows and add the new values. But it doesn't work quite right.
for (int i = 0; i < dgv.RowCount; i++)
{
JObject account = JsonConvert.DeserializeObject<JObject>(dgv.Rows[i].Cells["incomeAccount"].Value.ToString());
dgv.Rows[i].Cells["account"].Value = account["accountName"];
}
This console output actually shows the correct text, for instance, "John Smith". Howver when the grid is finished loading, the cells in that colunm are all blank. The datagridview column is not read only. Is there something else I need to do to get the new data to appear?
DataGridView likes data binding. Create an array of objects that have the properties you want to see, and then set that array to your DataGridView.DataSource property.
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.datasource(v=vs.110).aspx
The grid has to be the active control to update cell values after databinding. Calling dgv.focus() before the for loop fixed my problem.
Related
I have a data grid view with combo box column in it, i have bind that column to datatable like this:
((grdItems.Columns[1]) as DataGridViewComboBoxColumn).DataSource = dt;
((grdItems.Columns[1]) as DataGridViewComboBoxColumn).DisplayMember = "LocationName";
((grdItems.Columns[1]) as DataGridViewComboBoxColumn).ValueMember = "Id";
now i can get the selected value like this:
var value = grdItems.Rows[0][1].Value;
but the issue is, when i manually add the rows in the gridview (without binding the grid), i cant get the value of the combobox cell.
i am adding rows like this:
grdItems.Rows.Add(1, 1, "Some Value");
when i use
var value = grdItems.Rows[0][1].Value;
this method to get the value, i returns me the text of the cell not the value i.e 1 in this case.
How can i solve this issue? since i want the value of the cell in case of adding rows manually, as well as data-bind rows.
Am assuming that by manually adding rows you mean from the UI , so one way to get the value of the newly added row is to use an event handler for the events raised when you add an row. You may use one of the following
1) RowsAdded https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.rowsadded(v=vs.110).aspx 2) RowPrePaint - https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.rowprepaint(v=vs.110).aspx - not used this much but is also an option
this.myGridView.RowsAdded += new DataGridViewRowsAddedEventHandler(myGridView_RowsAdded);
private void myGridView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
var newRow = this.myGridView.Rows[e.RowIndex];
}
Edit: Based on the actual requirement stated in the comments - actual requirement being retrieving the newly added row's cell value (Id) corresponding to the combox box column on button save clicked event
Assuming you have bound the combo box to a data source itself , meaning, your
combobox.DataSource=someList
so what you can do is write a linq query
someList.Where( v=>v.Text.Equals("row.Cells[1].Value")).FirstOrDefault().Id
I have a stored procedure that returns 10 columns [column A, column B, etc].
Based off of that table, a winform ListBox is created listing those columns.
The items in the ListBox can be selected, then a "submit" button, which opens up a new Form with a DataGridView on it.
In the new Forms load event, I have placed code that iterates through the column collection and creates the structure of the DataGridView.
The columns I select show up, but the data is not populated into the returned rows.
StoredProcedures.up_Report_Adapter reportAdapter = new StoredProcedures.up_Report_Adapter();
gridCustomData.AutoGenerateColumns = false;
gridCustomData.DataSource = reportAdapter.GetData();
gridCustomData.Columns.Clear();
gridCustomData.Columns.Add(new DataGridViewColumn() { HeaderText = "REPORT_ID", CellTemplate = new DataGridViewTextBoxCell() });
foreach (var item in customReport.lstBoxSelectFields.SelectedItems)
{
gridCustomData.Columns.Add(item.ToString(), item.ToString());
}
gridCustomData.Refresh();
The right number of rows show up for the data, and if I put a break in at the gridCustomData.Refresh(), I can see that complete data for the columns selected from the ListBox.
So, how do I get the data to actually appear per defined row/column?
I have tried change the order of when the columns are created to before and after the gridCustomData DataSource is updated with the same results.
I also tried creating a BindingSource and using it as the DataSource for the DataGridView, then making the DataSource for the BindingSource the populated table adapter. The data is still not visible.
The goal is to create a "customized query", but really, it just means selecting the columns of what is in the DataSet. I am fetching the entire DataSet returned by the stored procedure (which itself is limited by parameters).
As a side note, if anyone knows of a thorough cookbook for these types of things, I would love to know what its title is. The API data from MSDN is useless as it uses contrived examples.
Bind to your datasource after setting up the columns.
First set the DataPropertyName for the column DataPropertyName = "REPORT_ID"
gridCustomData.Columns.Add(new DataGridViewColumn() { HeaderText = "REPORT_ID", CellTemplate = new DataGridViewTextBoxCell(), DataPropertyName = "REPORT_ID" });
Then bind to the datasource.
gridCustomData.DataSource = reportAdapter.GetData();
I'm adding a great deal of rows to a data grid view, and the process is pretty slow because it appears to try to redraw after each addition.
I'm having trouble finding an example online of how to create a List (or array, whichever works) of rows and add them all at once after the list is created. I need to do this to stop it from re-drawing after each addition though.
Can anyone provide a brief example of this or point me to a good doc?
You're probably looking for the DataGridView.DataSource property. See http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.datasource(v=vs.90).aspx
For example:
//Set up the DataGridView either via code behind or the designer
DataGridView dgView = new DataGridView();
//You should turn off auto generation of columns unless you want all columns of
//your bound objects to generate columns in the grid
dgView.AutoGenerateColumns = false;
//Either in the code behind or via the designer you will need to set up the data
//binding for the columns using the DataGridViewColumn.DataPropertyName property.
DataGridViewColumn column = new DataGridViewColumn();
column.DataPropertyName = "PropertyName"; //Where you are binding Foo.PropertyName
dgView.Columns.Add(column);
//You can bind a List<Foo> as well, but if you later add new Foos to the list
//reference they won't be updated in the grid. If you use a binding list, they
//will be.
BindingList<Foo> listOfFoos = Repository.GetFoos();
dgView.DataSource = listOfFoos;
A handy event to bind to at that point is the DataGridView.DataBindingComplete which fires after the data source is bound.
Here are a couple of ideas:
1) Bind a list to the DataGridView. When you set the DataGridView.DataSource = MyList, it immediately updates the entire grid without all the line-by-line action. You can add the items to MyList and then rebind to the DataGridView. (I prefer using a BindingList which will update the DataGridView grid dynamically.)
2) If data binding is not an option, what I've done in the past is set the AutoSizeMode = NotSet for each column before the update and then set it back to whatever it was before. It is the AutoSizeMode that really slows down the drawing.
I have two combo boxes in my form. i have binded these two with different database tables but with the same display member and some of data are repeated. When i change the index of first combo box ,the second combo box index also changed.
how to clear this problem. please any one give me the solution
Thanks
//dt1---> a b c d
//dt2---> x c a y
cmb_STable.SelectedIndex = -1;
cmb_STable.DisplayMember = "tablename";
cmb_STable.DataSource = dt1;
cmb_mTable.SelectedIndex = -1;
cmb_mTable.DisplayMember = "tablename";
cmb_mTable.DataSource = dt2;
// if cmb_mTable_SelectedIndexChanged with a
, the cmb_sTable also changed with a
Shot in the dark:
I assume you are using ADO.Net to databind the comboboxes. Depending on the API you will either have a bindingsource or a CurrencyManager in the background which has a copy of the databound list and a pointer to the current item.
My guess is that you have bound both lists to this datasource via the same CurrencyManager/BindingSource and moving it on one control moves it on the other.
You need to add a new BindingSource or currencymanager to stop this behaviour.
Your code still doesn't show everything.
It looks like there is a Databinding for the SelectedValue for both boxes. If they are bound to the same item (copy pasted?) , then that explains your problem.
I want to add a DataGrid to a Form. When the program executes, the user enters values and I use those values in the problem. I need a similar implementation for a table with two columns and when the user enters values I use them to for calculation in the program.
There is no requirement to save these values to a database, they are just going to be used in the program.
How do I do this in C#?
In a winforms environment, you can bind strongly typed collections as the datasource; Each property of the objects in the collection makes a column (Strictly speaking, I believe it works out the properties for the type that the collection returns, rather than the individual items in it)
If you are writing a WinForms App then you can use a DataTable to store the data and a DataGridView to display it. Simply create the DataTable:
dataTable = new DataTable();
Create the columns you need programatically:
var columnSpec = new DataColumn();
columSpec.DataType = typeof(decimal); // If it holds a decimal
columSpec.ColumnName = "Interest Rate";
dataTable.Columns.Add(columnSpec);
Add the DataGridView to the form using the Designer - but don't and then once the table has been created bind it to the grid using:
dataGridView.DataSource = dataTable;
You can set the properties on the grid from the designer view.
I have done this in a read-only case where the DataTable is populated from the program and just displayed it. All the user can do is resize, reorder or set the visibility on the columns. To add new rows you'll need to hook into the RowsAdded event
Re-wording Rowland Shaw
You need not have a database to bind to the datagrid. If you have the data filled in a strongly typed or a generic collection you can bind the datagrid to the collection. The datagrid will fill the data from the collection.
It will take the property names as the columns, and the rows will display as per the rows in the collection.
If you want user input, then I think you should consider using a better grid control. The datagrid is not suitable for this purpose. I dont' remember if flexgrid (the ocx one) has been redone for .Net.
You can use a datagridview and build a datatable and add columns through your code and set the datatasource of your datagridview as this datatable and set AllowUserToAddRows in properties window of Dataggridview to true ( true is the default value ).
If you want to make the calculation after a full ro update is made then you can use RowPrePaint event or if you want the calculation to be made after the data in each cell gets updated then you can use the CurrentCellChanged event of the datagridview.
Hope this helps....