DevExpress GridControl mainview not showing information - c#

I have a GridControl from Devexpress and I fill the control with a DataRow object. The row is added to the grid but the cells are empty. Here's the code:
DataTable dt = new DataTable();
dt.Columns.Add("Descripcion");
dt.Columns.Add("Cantidad");
dt.Columns.Add("Importe");
gridControl1.DataSource = dt;
clsLineaTicket newLn = new clsLineaTicket("Gin Tonic Beefeater", "1", "9,20");
DataRow dr = dt.NewRow();
dr[0] = newLn.strDescripcion;
dr[1] = newLn.strCantidad;
dr[2] = newLn.strImporte;
dt.Rows.Add(dr);
gridControl1.DataSource = dt;
The code is pretty simple, any idea why is not working? Thank you.

To solve your problem you should set the FieldNames of your GridColumns to the ColumnNames of your DataTable.
But i would strongly recommend you to use List<clsLineaTicket> instead of convert this to DataTable.
At first you already got an object and the Grid can handle this pretty well. So converting this to DataRows seems to be unnecessary. Don't forget any object needs space and a DataRow is still an object.
Further a List<clsLineaTicket>brings you Object access instead of DataRow access. This is more readable and better for refactorings. So you could easily rename a Property via refactoring. But how to rename a column in your DataTable? You access row["ColumnName"] sometimes? Then you are lost because magic string can't be refactored. Let me show small example for better readablity of List<T>:
Think you are in the event for a double click and you would to show the price of your ticket:
//This event is just a dummy and doesn't exists this way
private void grid_click(object sender, EventArgs e)
{
//DataTable access
var row = gridview.GetFocusedRow() as DataRowView;
MessageBox.Show(Convert.ToString(row["Price"]);
//List access
var lineaTicket = gridView.GetFocusedRow() as LineaTicket; //You directly see it's a ticket here
MessageBox.Show(lineaTicket.Price); //You don't need conversion
}
Another goodie is the possibility of Lambda and Linq. You need a SubList with alle Tickets which got a price lower 10$?
List<clsLineaTicket> lowPriceTickets = ticketList.FindAll(ticket=>ticket.Price < 10);
If you using a List make sure your FieldNames correspond to Propertynames. If you want to make the Grid editable you also need to implement setter on your Properties.
Hope this helps.

Related

Custom sorting order - DataGridView

Is it possible to sort this in a datagridview without padding the data to 3 values after the +.
The datatype is string and the datagridview column is text.
10:10+01
10:10+100
10:10+110
10:10+10
Should sort like this
10:10+01
10:10+10
10:10+100
10:10+110
Maybe changing the sortingmode to programmatic might help?
Any input would be appreciated
Edit: Example of the data being copied to dt and then bound with a dataview.
DataTable dtTest = new DataTable();
dtTest.Columns.Add("Column1", typeof(string));
dtTest.Rows.Add("10:11+1");
dtTest.Rows.Add("10:11+101");
dtTest.Rows.Add("10:11+101");
dtTest.Rows.Add("10:11+2");
dtTest.Rows.Add("10:11+200");
dtTest.Rows.Add("10:10+1110");
DataView dvTest = new DataView(dtTest);
dataGridView1.DataSource = dvTest;
Example sort ordering
10:10+1110
10:11+1
10:11+101
10:11+101
10:11+2
10:11+200
Custom sorting an unbound DataGridview
Not sure about your data, but taking them literally this will do the job for an unbound DataGridView DGV:
First you need to hook up a SortCompare handler, maybe like this
DGV.SortCompare += new DataGridViewSortCompareEventHandler( this.DGV_SortCompare);
If necessary you can call it on your column (or let the Header click do the job):
DGV.Sort(DGV.Columns[yourColumn], ListSortDirection.Ascending);
This is the SortCompare event code. It uses simple string manipulation to create a sortable version by padding the last part with zeroes.
private void DGV_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
{
string s1 = e.CellValue1.ToString().Substring(0, 6) +
e.CellValue1.ToString().Substring(6).PadLeft(5, '0');
string s2 = e.CellValue2.ToString().Substring(0, 6) +
e.CellValue2.ToString().Substring(6).PadLeft(5, '0');
e.SortResult = s1.CompareTo(s2);
e.Handled = true;
}
There is a comprehensive discussion of three methods to sort a DGV here on MSDN. - Clearly this is the easiest one for your problem. Also rather flexible: You can use the e.columnIndex parameter to create spearate comparison strings for other columns as well..
If other columns need no special sorting code you should insert this line to the beginning of the SortCompare:
if (e.Column.Index != yourColumn) return;
Custom sorting a data bound DataGridView
Update: Since you have changed your question to a DataBound DGV, here is a similar solution for this case:
BindingSource BS = new BindingSource();
private void sortButton_Click(object sender, EventArgs e)
{
DT.Columns.Add("TempSort");
foreach (DataRow row in DT.Rows)
{
string val = row[yourcolumn].ToString();
row["TempSort"] = val.ToString().Substring(0, 6) +
val.ToString().Substring(6).PadLeft(5, '0');
}
BS.DataSource = DT;
BS.Sort = "TempSort ASC";
DT.Columns.Remove("TempSort");
DGV.DataSource = BS;
}
This solution assumes your DataSource is a DataTable DT and will create a temporary column called "TempSort"`and fills it with the prepared version of the data values; it will sort ascending.
For the sorting we use a BindingSource.
To control the right column (here called 'yourcolumn') dynamically as well as the sort order, you will have to write some code yourself, responding to the ColumnHeaderClick...

Datasource not reflecting sorting in DataGridView

I am binding a DataTable as the DataSource of a DataGridView. I enabled the SortMode property to Automatic for all DataGridViewColumn. But when I am sorting on DataGridView the Sort change is not being reflected in the underlying DataSource which is the DataTable.
For example:
DataTable table = new DataTable();
table.Columns.Add("Name");
table.Columns.Add("Age", typeof(int));
table.Rows.Add("Alex", 27);
table.Rows.Add("Jack", 65);
table.Rows.Add("Bill", 22);
dataGridView1.DataSource = table;
Now if I was to get the selected row like below it will always return the row at 0 Index in the DataTable even after sorting which is Alex, 27.
DataRow newRow = table.NewRow();
newRow.ItemArray = table.Rows[dataGridView1.Rows.IndexOf(dataGridView1.SelectedRows[0])].ItemArray.Clone() as object[];
Can someone please suggest how I should go about this situation?
First of all the DataTable object is detached from DataGridView even if you bind it to DataSource, that is, if you change your DataGridView it will not affect your DataTable. And in your case you want the sorting in DataGridView to be reflected in DataTable. And so for that reason you need to catch an event every time there is changes in ordering/sorting in DataGridView. You need to catch therefore for that regard the ColumnHeaderMouseClick event of the DataGridView.
Another important thing is, in achieving a synchronize sorting of both DataTable and DataGridView is the DefaultView method of Datable class that has the Sort property. So, what we are going to do is every time the DataGridView is changed sorting-wise we will sort the DataTable also.
First of all we need to make a DataTable object global so that we could access it anywhere later on.
DataTable table;
Secondly, we need to initialize an event listener for ColumnHeaderMouseClick and for our practical purpose we will set it at Form constructor.
InitializeComponent();
dataGridView1.ColumnHeaderMouseClick += new DataGridViewCellMouseEventHandler(dataGridView1_ColumnHeaderMouseClick);
We then have this empty Mouse event handler:
void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
}
And if the above method doesn't automatically come out, just copy and paste in your code.
And for the sake of illustration we will add the DataTable during the Form Load and in this case I am going to use your own code:
table = new DataTable();
table.Columns.Add("Name");
table.Columns.Add("Age", typeof(int));
table.Rows.Add("Alex", 27);
table.Rows.Add("Jack", 65);
table.Rows.Add("Bill", 22);
dataGridView1.DataSource = table;
And then finally we will put some code in the ColumnHeaderMouseClick event:
void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (dataGridView1.SortOrder.ToString() == "Descending") // Check if sorting is Descending
{
table.DefaultView.Sort = dataGridView1.SortedColumn.Name + " DESC"; // Get Sorted Column name and sort it in Descending order
}
else
{
table.DefaultView.Sort = dataGridView1.SortedColumn.Name + " ASC"; // Otherwise sort it in Ascending order
}
table = table.DefaultView.ToTable(); // The Sorted View converted to DataTable and then assigned to table object.
}
You could now use table object and sorted according to the sorting order of the DataGridView.
Just to confirm my claim, we will make a button in your form named button1 and when clicked it will show the first row and the sorted column value, like:
private void button1_Click(object sender, EventArgs e)
{
String sortedValue = dataGridView1.SortedColumn.Name == "Name" : table.Rows[0][0].ToString() ? table.Rows[0][1].ToString();
MessageBox.Show(sortedValue);
}
You can put your DataTable into BindingSource container and set this class to data source of DataGridView.
BindingSource bindingSource1 = new BindingSource();
bindingSource1.DataSource = dataTable;
dataGridView1.DataSource = bindingSource1;
// another grid view options...
To learn about BindingSort, see this link.
Old question, but still no easy solution mentioned, so I post it here for the people looking for the answer nowadays:
DataRow row = ((DataRowView)yourDataGridView.SelectedRows[0].DataBoundItem).Row;
int index = yourDataTable.Rows.IndexOf(row);
index will be the index of the row in your DataTable corresponding with the selected row in DataGridView, however you have sorted it.
For others coming here for same reason as I.
I couldn't get the underlying data sorted either, thus when I was deleting a row, it was deleting the wrong one.
I found DataTable will not be sorted but only DataTable.DefaultView will be.
So instead of DataRow row = dataTable.Rows[0];
You would do DataRow row = dataTable.DefaultView[0].Row;
I found another alternative solution where I get value of a unique column from my DataGridView and then query the underlying DataSource the DataTable to get the rows even though the DataTable is not sorted.
But I'd like to know how to sort the DataTable though.
Solution

DataGridView with DataTable data source: how to efficiently extract selected rows?

I am showing a DataGridView control on my form, populating it with a DataTable object through the DataSource property of the control. I set the control to select the entire row when it is selected, and enabled multiselect. All of this works swimmingly.
A user can select multiple rows and click a button. I want to make a new DataTable object with copies of the selected rows and pass that to a Crystal Report.
Is there an efficient means of doing this? It seems the only way is to parse the new rows for the new DataTable from the selected grid cells, which strikes me as relatively ridiculous.
This is my solution to the question "How to get selected Rows as DataTable":
copy structure of original DataTable
copy each row (as a row may exist only in one datatable object)
DataTable selectedRows = (sourceDataGridView.DataSource as DataTable).Clone();
foreach(DataGridViewRow row in sourceDataGridView.SelectedRows) {
selectedRows.Rows.Add((row.DataBoundItem as DataRowView).Row.ItemArray);
}
I've found that the best way to avoid iterating over the DataTable to find the rows you want is to bind to a DataView instead. This way, you can sort and all that other fun stuff you like to do with a DataGridView, and can still get the data you need without manually parsing the underlying DataTable.
Below is a succinct example that should show you everything you need to get a DataRow without searching:
DataGridView dataGridView1 = new DataGridView();
DataTable tb = new DataTable();
DataView dv = tb.AsDataView();
dataGridView1.DataSource = dv;
// Get the row indexes in whatever your favorite manner is.
List<int> selectedRowIndexes = YourGetSelectedRowIndexesMethod();
foreach(int selectedRowIndex in selectedRowIndexes)
DataRow dr = dv[selectedRowIndex].Row;
One quick method to get the selected indexes (just in case you need it):
List<int> indexes = new List<int>();
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
indexes.Add(row.Index);
}

How can I clear rows in DataGridView with C#?

Following Error in this line.
datagridview1.Rows.Clear()
but this line gives error:
Cannot clear this list.
I also had similiar problem when I try to clear DataSource of a DataGridView after I had binded it to a DataTable with:
DataTable DT = ... ; // fill it
datagridview1.DataSource = DT;
when I try to clear it's rows later with the following code:
datagridview1.DataSource = null
I get this error:
ERROR: Object reference not set to an instance of an object
This object reference ERROR problem already solved in here. But I managed to solve my own problem (clearing DataGridView rows) with this code:
DataTable DT = (DataTable)datagridview1.DataSource;
if (DT != null)
DT.Clear();
I know that this question was asked a very long time ago, but I hope my solution would solve someone problems.
Is your DataGridView bound to a DataSource, i think thats why its not allowing you to clear it since its bound to an underlying DataTable or List.
you could try setting the DataSource Property to null
datagridview1.DataSource = null; for clearing
private void button_Limpar_Click(object sender, EventArgs e)
{
DataTable DT = (DataTable)dataGridView_Cidade.DataSource;
if (DT != null)
DT.Clear();
}
#endregion
Simply add this line at beginning of your event:
dgv_nameOfGridView.DataSource=false;
Now every time you click it will erase the dgv..
You have to Clear datasource not datagridview rows.
datagridview1.DataSource = null;
Another way is
1) Dont assign direct datasource to gridview.
add rows from datatable to gridview
foreach (DataRow row in dataTable.Rows)
{
var dataGridRow = new DataGridViewRow();
dataGridRow.CreateCells(datagridview1);
for (int i = 0; i < row.ItemArray.Length; i++)
{
dataGridRow.Cells[i].Value = row.ItemArray[i];
}
datagridview1.Rows.Add(dataGridRow);
}
then use
datagridview1.Rows.Clear()
You can use this simple method:
First clear your DataTable and then refresh your DataGridView
dataTable.Clear();
dataGridView.Refresh();
Hope this help
Easy solution is to clear the DataSet.
ds.Clear();
Since you are using a bound grid, have you tried to call your loading
function twice and verified that the data is not doubling?
Since it is bound, loading twice ought to not duplicate the data.
http://www.vbforums.com/showpost.php?s=aa5f116586c00a2d9ea15e3727fc5c2f&p=2841192&postcount=9
First clear DataSource and then clear DataGridView
in VB
datagridview1.DataSource = Nothing
datagridview1.Rows.Clear()
hope help
If you load your DataGridView with a parameter, you can send an empty parameter to it. This will clear your DataGridView without having to set its DataSet to null.
For example, I load my DataGridView with a Code, when I fill a TextBox.
this.dataTable1TableAdapter.Fill(this.ds_MyDataSet.DataTable1, TextBox1.Text);
If I want to clear its content, then
this.dataTable1TableAdapter.Fill(this.ds_MyDataSet.DataTable1, "");
Here we are 8 years later.
Although
datagridview1.DataSource = null;
is a satisfactory answer for most, for me this removes all customizations I've added to the columns in design view. So hidden columns appears if I want to clear out the rows.
So rather than clear out rows:
datagridview1.Rows.Clear()
Clear out the DataTable or DataView that you used to set up the DataGridView. Note you don't have to check if something is null nor worry about Object not set to reference errors.
So here's how I did mine:
//Populate the datagridview
DataTable _DT = new DataTable();
BindingSource _BS = new BindingSource();
//Initially fill up your datatable with stuff
//You can call this method again if data needed to be changed
public void fillDT(int id) {
_DT = fillUpDataTableWithStuffFromDB(id);
_BS.DataSource = _DT.DefaultView;
datagridview1.DataSource = _BS;
_BS.ResetBindings(false);
}
//You can use this method to mimic the functionality above
//But rather fetching data, just clear out the datatable and pass it in
public void clearDT() {
_DT.Clear();
datagridview1.DataSource = _DT.DefaultView;
datagridview1.Refresh();
}
As you can see above, I just cleared out the datatable, and passed that into the datagrid. This kept all my properties I set on the datagridview column.
foreach (DataGridViewRow item in this.datagridview.Rows)
{
datagridview.Rows.RemoveAt(item.Index);
}
I had the same problem I tried with many solutions.
In the end I realized that we can't clear the DataGridView if we use it's property "DGV.Datasource" because DGV takes its data from the dataset so you need to clear the DataTable rows
Dataset.Tables["TableName"].Rows.Clear();
If you use this function in the Load of the Form you need to add a condition
if (DataSet.Tables["TableName"] !=null)
Dataset.Tables["TableName"].Rows.Clear();
or you will get this error
Object reference not set to an instance of an object.

C#.net datagrid

How to add child rows in datagrid c#.net windows forms?
I'm not sure if this is what you're asking, but if you want to append rows you're easiest way is to append them to whatever DataSource you're using before you DataBind()
If this wasn't what you're after, please provide more detail.
Usually you bind the datagrid to a dataset. Could you please clarify what you are looking for so that we can get into more detail?
DataTable myDataTable = new DataTable();
DataGridView myGridView = new DataGridView();
myGridView.DataSource = myDataTable;
DataRow row = myDataTable.Rows.Add(1, 2, 3, 4, 5); //This adds the new row
If you are looking for a nested table, you'll have to go with a third-party control. The DataGridView doesn't support it.
Firstly sure your data GridView name and create DataTable
DataTable DT= new DataTable();
then also create DataRow
DataRow row = new DataRow();
and last call the add() function Like this:
DT.Rows.Add("ID","Name","Addr","number");
and don't miss to set source on DataGrideView for Showing data :
DataGrideView.DataSource = DT;

Categories

Resources