Inserting an empty row in DataGridView - c#

I want to introduce a graphical separation between group of rows in a DataGridView.
Which are the options I have:
- Should I introduce an empty row?
- Should I work with borders and/or the paint methods ?

This increases the lower border of the row at specified [Index]:
DataGridViewRow row = dataGridView1.Rows[Index];
row.DividerHeight = 1;
Note that DividerHeigth uses the space of the row, so if you set it to 10 it can cover half row (for me, 1 is enough).
There is also DividerWidth property to separate groups of columns.

grid.Rows.Insert(index, 1);
var addedRow = grid.Rows[index];
This inserts 1 empty templated row at 'index'.

With the Rows.Add() method you add a new row, you can obtain a reference to it by using:
var newRow = dg.Rows[dg.Rows.Add()];
So you can manipulate your new row after, example:
newRow.Cells["myColumn"].Value = "asd";

DataGridViewRow DGVR= (DataGridViewRow)yourDataGridView.Rows[0].Clone();
DGVR.Cells[0].Value = "XYZ";
DGVR.Cells[1].Value = 50.2;
yourDataGridView.Rows.Add(DGVR);

Related

How to hide data of a specific cell in DataGridView

I have a Datagridview
1 Drink1 Beef1
2 Drink2 Beef2
3 Drink3 Beef3
But now I want to hide only "Drink3" and the rest stay the same.
I'm only aware of how to hide/remove rows and columns but not sure if it's possible for an individual cell. If it is, what should I apply here? I'm thinking of an datagridview Event but just can't find what it is.
The result should look like this.
1 Drink1 Beef1
2 Drink2 Beef2
3 Beef3
If you want just don't show the value, you can clear it. You now Cell is read-only and you can change the Visible directly.
dataGridView1.Rows[Your Row].Cells[Your Col].Value = null;
If you need cell data you can achieve it from the Data Table.
You can clear the value - but you'll be deleting it from linked data source as well.
Other way to do it would be to set that cell's:
cell.CellStyle.ForeColor = cell.CellStyle.BackColor
cell.CellStyle.SelectionForeColor = cell.CellStyle.SelectionBackColor
Thus making data invisible.
But in this case user can still copy and paste the value, so you'd have to disable copying values from this DataGridView as whole or intercept copy event and if user is copying from "forbidden" cell, just cancel the event.
You can change the cell's style in the backend code, you can change the cell's String value to "".
While you might hide the result as sugested, such as amending your forecolor and back color, I would not recommend it. In some cases (highlited content for instance) it may become visible.
If you don't need to work with the content after you load it into the DataGridView, you can erase the content directly in your data query (SQL, LINQ) or in DataTable.
If you have to work with the content at runtime after you load the DataGridView, than clone source DataTable, hide the content and present that new one. One can figure out more ways to apply this principle.
C#
DataTable dt;
dt = ds.table(0);
for (var ir = 0; ir <= dt.Rows.Count - 1; ir++)
{
DataRow dr = dt.Rows(ir);
if (CStr(dr("MyColumn")) = "Drink3")
{
dr("MyColumn") = " ";
}
}
this.DataGridView1.DataSource = dt;
VB:
Dim dt As DataTable
dt = ds.table(0)
For ir = 0 To dt.Rows.Count - 1
Dim dr As DataRow = dt.Rows(ir)
If CStr(dr("MyColumn")) = "Drink3" Then
dr("MyColumn") = " "
End If
Next
Me.DataGridView1.DataSource = dt

DataGridView row header cell text visibility

I have a DataGridView in my WinForms application. Basically, I want to input some 2D data there or something like that. It means, that I want to have both columns named and rows named. And so I did. But then there was a problem. When it's fine with column names, the row names tend to be not visible. For example:
The code I use to somehow "beautify" the DataGridView:
private void BeautifyTable(TableView tableView)
{
foreach (DataGridViewRow row in tableView.Rows)
{
row.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
}
foreach (DataGridViewColumn col in tableView.Columns)
{
col.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
}
TableView is a class created by me, and it inherits from DataGridView.
So now my question would be: Is there a way to somehow make those row names/titles appear in a normal way (in this particular case those are: s0, s1, s2.., but they're like cut from the left side).
P.S Is there a good way to "stretch" the columns? I mean if I have f.e 10 columns they would fill the whole DataGridView width, but if I would add (I do this dynamically) 5, so there would be 15 columns, still they would fit, just the width of every column would decrease?
Increase the width of the row header:
dataGridView1.RowHeadersWidth =
dataGridView1.RowHeadersWidth * 2; // or another value
Try to hide those arrows by setting the RowHeadersVisible to False in the properties of the datagridview at the Form.cs [Design] or just simply add the code below.
Me.DataGridView1.RowHeadersVisible = False
I actually found the best answer by myself.
You can set the WitdthSizeMode also for row headers, like this:
tableView.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;
And that's the result:

Displaying original rowindex after filter in datagridview

Just want to ask on how to get the original row index of selected row in DataGridView after filter.
I have DataGridView with 2 columns :name and age. And I have a TextBox that serves as filter. Let's say I have 8 records and upon filtering it goes to only 4 records and upon clicking the last record, I get row index of 4, while I need to get the original index of this row and display it on MessageBox. How will I do it?
Thank you.
Original row index means the index of the DataRow in the DataTable which can be found by DataTable.Rows.IndexOf(row). So to find the original index of the row you can use the following code:
var r = ((DataRowView)BindingContext[dataGridView1.DataSource].Current).Row;
var index = r.Table.Rows.IndexOf(r);
In case you are interested to do that for all rows in the DataGridView, as also is mentioned by Taw in comments, you can look into the DataBoundItem of the DataGridViewRow:
var r = ((DataRowView)dgvRow.DataBoundItem).Row; // dgvRow is a row of the DataGridView
var index = r.Table.Rows.IndexOf(r);
From your comments you said that you need it to display current record selected so I will not directly answer How to get row index on filtered table but how to get current record selected.
So to simply get current selected record use this code:
//Use this one if your datagridview SelectionMode is not FullRowSelect
DataGridViewRow row = dataGridView1.Rows[dataGridView1.SelectedCells[0].RowIndex];
string name = row.Cells["Name"].Value.ToString();
int age = Convert.ToInt32(row.Cells["Age"].Value);
//If your datagridview SelectionMode is FullRowSelect then use this
DataGridViewRow row = dataGridView1.SelectedRows[0];
string name = row.Cells["Name"].Value.ToString();
int age = Convert.ToInt32(row.Cells["Age"].Value);
Reza answered main part of your question but if for some reason it is not working you can use this since your primary key is your NAME
foreach(DataRow r in yourDataTable.Rows)
{
if(r["NAME"].ToString() == row.Cells["Name"].Value.ToString()) //This row.cells... is the one from above code
{
int originalRowIndexInDataTable = dt.Rows.IndexOf(r);
return;
}
}

How to set Cell value of DataGridViewRow by column name?

In windows forms, I'm trying to fill a DataGridView manually by inserting DataGridViewRows to it, so my code looks like this:
DataGridViewRow row = new DataGridViewRow();
row.CreateCells(dgvArticles);
row.Cells[0].Value = product.Id;
row.Cells[1].Value = product.Description;
.
.
.
dgvArticles.Rows.Add(row);
However, I would like to add the Cell value by column name instead of doing it by the index, something like this:
row.Cells["code"].Value = product.Id;
row.Cells["description"].Value = product.Description;
But doing it like that throws an error saying it couldn't find the column named "code".
I'm setting the DataGridView columns from the designer like this:
Am I doing something wrong? How can I accomplish what I want to do?
So in order to accomplish the approach you desire it would need to be done this way:
//Create the new row first and get the index of the new row
int rowIndex = this.dataGridView1.Rows.Add();
//Obtain a reference to the newly created DataGridViewRow
var row = this.dataGridView1.Rows[rowIndex];
//Now this won't fail since the row and columns exist
row.Cells["code"].Value = product.Id;
row.Cells["description"].Value = product.Description;
I tried it too and got the same result. This is a little verbose, but it works:
row.Cells[dataGridView1.Columns["code"].Index].Value = product.Id;
When you use the ColumnName indexer of the DataGridViewCellCollection, internally it tries to get the column index using the ColumnName from the owning/parent DataGridView of this DataGridViewRow instance. In your case the row hasn't been added to the DataGridView and hence the owning DataGridView is null. That's why you get the error that It couldn't find the column named code.
IMO the best approach (same as Derek's) would be to the add the row in the DataGridView and use the returned index to the get the row instance from the grid and then use the column name to access the cells.
The problem is that referencing cells by name doesn't work until the row is added to the DataGridView. Internally it uses the DataGridViewRow.DataGridView property to get at the column names, but that property is null until the row is added.
Using C#7.0's local function feature, the code can be made halfway readable.
DataGridViewRow row = new DataGridViewRow();
row.CreateCells(dgvArticles);
DataGridViewCell CellByName(string columnName)
{
var column = dgvArticles.Columns[columnName];
if (column == null)
throw new InvalidOperationException("Unknown column name: " + columnName);
return row.Cells[column.Index];
}
CellByName("code").Value = product.Id;
CellByName("description").Value = product.Description;
.
.
.
dgvArticles.Rows.Add(row);
Another alternative:
Suppose the name of your DataGridView is dataGridView1.
var row = new DataGridViewRow();
// Initialize Cells for this row
row.CreateCells(_dataGridViewLotSelection);
// Set values
row.Cells[dataGridView1.Columns.IndexOf(code)].Value = product.Id;
row.Cells[dataGridView1.Columns.IndexOf(description)].Value = product.Description;
// Add this row to DataGridView
dataGridView1.Rows.Add(row);

Adding rows and columns programmatically [duplicate]

I'm sending values from one form to another form, then want to display in dgv,
I'm trying this, there is no error during execution, bt it does not show data in dgv..
lineItemsDGV.Rows.Add();
int RowIndex = lineItemsDGV.RowCount - 1;
DataGridViewRow NewRow =lineItemsDGV.Rows[RowIndex];
NewRow.Cells[0].Value = item.Product_id;
NewRow.Cells[1].Value = item.product_name;
NewRow.Cells[2].Value = item.specification;
NewRow.Cells[3].Value = item.unit_price;
NewRow.Cells[4].Value = item.unit_price * 1;
You're close.
What you can do is use the return value of your call to DataGridViewRowCollection.Rows.Add() method, which is the index value of the just added row.
Change your code to this:
int RowIndex = lineItemsDGV.Rows.Add();
DataGridViewRow NewRow = lineItemsDGV.Rows[RowIndex];
NewRow.Cells[0].Value = item.Product_id;
NewRow.Cells[1].Value = item.product_name;
NewRow.Cells[2].Value = item.specification;
NewRow.Cells[3].Value = item.unit_price;
NewRow.Cells[4].Value = item.unit_price * 1;
This is how I would do it:
DataRow rowToAdd= myTable.NewRow();
rowToAdd["ProductId"] = item.Product_id;
rowToAdd["ProductName"] = item.product_name;
rowToAdd["Specification"] = item.specification;
rowToAdd["UnitPrice"] = item.unit_price;
myTable.Add(rowToAdd);
And bind the datatable to the gridview.
I know this thread is old, but I found this page helpful today and this is how I accomplished adding a new row which is different than the previous solutions.
Assumption:
datagridview has columns specified at design time. In my case I had 3 text columns.
The solution is to use the DataGridViewRowCollection.Add functionality and pass a parameter array that contains a list of each column value separated by a comma.
DataGridView1.Rows.Add("Value 1", "Value 2", "Value3")
Using this approach, there's no need to use the BeginEdit, Update or Refesh dgv functions.

Categories

Resources