My motive is to display some information as link and on click of that, I should be able to get id of clicked item and open new window with detailed information of item. As i am new in win forms but i did some research, Possible option for this might be DataGridViewLinkColumn but i am not able to link id with column data and click event on which open new window.
Or there any other better approach possible.?
When you have a datagridview you can get the values of a cell as follows:
Firstly, create a cellclick event
datagridview1.CellClick+= CellClickEvent;
DataGridViewCellEventArgs holds some properties, these would be rowindex (row you clicked) and columnindex (column you clicked) and some other...
make a datagrid with 2 columns, column 0 holds the Id of the row, column 1 holds the link
void CellClickEvent(object sender, DataGridViewCellEventArgs e)
{
if(e.ColumnIndex == 1) // i'll take column 1 as a link
{
var link = datagridview1[e.columnindex, e.rowindex].Value;
var id = datagridview1[0, e.rowindex].Value;
DoSomeThingWithLink(link, id);
}
}
void DoSomeThingWithLink(string link, int id)
{
var myDialog = new Dialog(link,id);
myDialog.ShowDialog();
myDialog.Dispose(); //Dispose object after you have used it
}
I'm assuming you're using a DataGridView element.
What you could do is use the CellClick event of the object. It will have a DataGridViewCellEventArgs object passed on, on which there's a ColumnIndex property and a RowIndex property. This way you could figure out where in the the datagrid the user clicked.
And, for example, you could use that information to look up the id or other info since you now know the row & the cell the user clicked on.
arbitrary e.g.:
// wire up the event handler, this could be anywhere in your code
dataGridView.CellClick += dataGridView_CellClick; // when the event fires, the method dataGridView_CellClick (as shown below) will be executed
private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
var rowIndex = e.RowIndex;
var columnIndex = e.ColumnIndex; // = the cell the user clicked in
// For example, fetching data from another cell
var cell = dataGridView.Rows[rowIndex].Cells[columnIndex];
// Depending on the cell's type* (see a list of them here: http://msdn.microsoft.com/en-us/library/bxt3k60s(v=vs.80).ASPX) you could cast it
var castedCell = cell as DataGridViewTextBoxColumn;
// Use the cell to perform action
someActionMethod(castedCell.Property);
}
(*DataGridViewCell types: http://msdn.microsoft.com/en-us/library/bxt3k60s(v=vs.80).ASPX)
Related
I need to allow the user to select a row by clicking on the row header to allow row deletion, but when the row header is clicked, the first cell gets focus and the text is highlighted, which I need to prevent so the user can't make accidental edits to that first cell.
Here's an example of what's happening:
As you can see, the first cell has focus and the user can edit that cell, when all that was done was the row header was clicked.
I tried the answer to this SO question, but neither event fired when I clicked a row header. Here's the code that I used for that attempt:
private void dgvCategories_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
{
if (e.StateChanged == DataGridViewElementStates.Selected)
{
Console.WriteLine("true");
dgvCategories.ReadOnly = true;
}
}
private void dgvCategories_CellStateChanged(object sender, DataGridViewCellStateChangedEventArgs e)
{
if (e.StateChanged == DataGridViewElementStates.Selected)
{
Console.WriteLine("false");
dgvCategories.ReadOnly = false;
}
}
I also tried experimenting with the various DataGridViewEditMode options, but none of those accomplished what I need.
The DGV SelectionMode is set to RowHeaderSelect.
I still need to be able to grab the hidden "id" field in the row for the delete process. Here's my code for that:
private void btnDeleteRow_Click(object sender, EventArgs e)
{
int index = dgvCategories.SelectedRows[0].Index;
string rowId = dgvCategories[0, index].Value.ToString();
string deleteString = string.Format("DELETE FROM masterfiles.xref WHERE id = " + rowId);
conn.Open();
NpgsqlCommand deleteCmd = new NpgsqlCommand(deleteString, conn);
deleteCmd.ExecuteNonQuery();
conn.Close();
}
That works; I just need to prevent that first cell from automatically getting focus for editing when the row is selected. I still need to allow the user to select individual cells for editing, as well.
Try :
1- make the DataGridView selection by one row instead of one cell .
2- Disable allowing user to edit the DataGridView.
3- Make DataGridView ReadOnly .
Do 1 & 2 all the time except at editing operation .
I have a View Model in which my data is stored to be used on the presenter and window. However, I now need to get (when pressing a button) the current row's results on the grid into my view model. I first used the mouse double click event, but the requirements changed from that to a button on the form:
private void dgvResults_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (this.colOrderNo.Index != e.ColumnIndex || e.RowIndex < 0) return;
var auditOrder = (PurchaseOrdersTrackingViewModel) this.dgvResults.Rows[e.RowIndex].DataBoundItem;
this.AuditOrderKey = $"{auditOrder.OrderNo}|{auditOrder.ItemNo}|{auditOrder.WarehouseId}|{auditOrder.ItemSequence}";
}
That's my old code. Now I need that here:
private void btnAuditLog_Click(object sender, EventArgs e)
Not sure how to refer to the RowIndex without the DataGridViewCellMouseEventArges event. I tried the CurrentRow property, but it doesn't do the job.
Just another question on the fly, if someone could assist with that as well, how do I get a value from one form to another, spesifically a properties value. It's not on the grid, in a control. It's basically just public string order that's all. I set the value on one form, then need it for query filtering on another. Let me know if you need anything else.
You want to use the SelectedRows property of the DataGridView. It tells which row is selected. In this case, you seem to want the first selected row (since you have a single property called this.AuditOrderKey).
The column order no to longer matters in this context.
if (dgvResults.SelectedRows.Count == 0) return;
var auditOrder = (PurchaseOrdersTrackingViewModel) dgvResults.SelectedRows[0].DataBoundItem;
this.AuditOrderKey = $"{auditOrder.OrderNo}|{auditOrder.ItemNo}|{auditOrder.WarehouseId}|{auditOrder.ItemSequence}";
If you don't have selected rows, CurrentRow is an option:
if (dgvResults.CurrentRow == null) return;
var auditOrder = (PurchaseOrdersTrackingViewModel) dgvResults.CurrentRow.DataBoundItem;
this.AuditOrderKey = $"{auditOrder.OrderNo}|{auditOrder.ItemNo}|{auditOrder.WarehouseId}|{auditOrder.ItemSequence}";
Use the SelectedRows property of the DataGridView. Assuming that you set your DataGridView as MultiSelect = false; and SelectionMode = FullRowSelect;
if (dgvResults.SelectedRows.Count > 0)
{
dgvResults.SelectedRows[0].Cells["yourColumnName"].Value.ToString();
}
In your button click event, it will look like this. (Assuming that your button name is btnEdit)
private void btnEdit_Click(object sender, EventArgs e)
{
if (dgvResults.SelectedRows.Count > 0)
{
string selectedValue = dgvResults.SelectedRows[0].Cells["yourColumnName"].Value.ToString();
}
}
I want a Delete button at the end of each row of DataGridView and by clicking that I want to remove the desired row from the binding list which is data source of my grid.
But I can't seem to do it I have created a button object in product class and instantiated it with the unique id to remove that object from list. but button is not showing in the row.
There are TextBoxes in the form and users can enter text, and when they press Add button, a new object of product is instantiated with the provided fields and then it is added to the BindingList.
Finally this list is bound to the DataGridView and details are shown in the grid. (I have done this part).
and at last by clicking save button the list is saved in the DB.
public class Product{
public string Brand { get; set; }
public int ProductPrice { get; set; }
public int Quantity { get; set; }
public product(string brand,int productPrice, int quantity){
this.Brand = brand;
this.ProductPrice = productPrice;
this.Quantity = quantity;
}
}
public partial class MainForm: Form{
.....
BindingList<Product> lProd = new BindingList<Product>();
private void btnAddProduct_Click(object sender, EventArgs e){
string Brand = txtProBrand.Text;
int Price = Convert.ToInt32(txtPrice.Text);
int Quantity = Convert.ToInt32(txtQuantity.Text);
Product pro = new Product(Brand, Price, Quantity);
lProd.Add(pro);
dataGridView1.DataSource = null;
dataGridView1.DataSource = lProd;
}
.....
}
To show a button on DataGridView rows, you should add a DataGridViewButtonColumn to columns of your grid. Here is some common tasks which you should know when using button column:
Add Button Column to DataGridView
Show Image on Button
Set Text of Button
Handle Click Event of Button
Add Button Column to DataGridView
To show a button on each row of your grid, you can add a DataGridViewButtonColumn to columns of your grid programmatically or using designer:
var deleteButton=new DataGridViewButtonColumn();
deleteButton.Name="dataGridViewDeleteButton";
deleteButton.HeaderText="Delete";
deleteButton.Text="Delete";
deleteButton.UseColumnTextForButtonValue=true;
this.dataGridView1.Columns.Add(deleteButton);
Show Image on Button
If you prefer to draw image on button, you should have an image in a resource and then handle CellPainting event of your grid:
void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex == dataGridView1.NewRowIndex || e.RowIndex < 0)
return;
if (e.ColumnIndex == dataGridView1.Columns["dataGridViewDeleteButton"].Index)
{
var image = Properties.Resources.DeleteImage; //An image
e.Paint(e.CellBounds, DataGridViewPaintParts.All);
var x = e.CellBounds.Left + (e.CellBounds.Width - image.Width) / 2;
var y = e.CellBounds.Top + (e.CellBounds.Height - image.Height) / 2;
e.Graphics.DrawImage(image, new Point(x, y));
e.Handled = true;
}
}
Set Text of Button
You can use either of these options:
You can set Text property of your DataGridViewButtonColumn and also set its UseColumnTextForButtonValue to true, this way the text will display on each cells of that column.
deleteButton.Text="Delete";
deleteButton.UseColumnTextForButtonValue=true;
Also you can use Value property of cell:
this.dataGridView1.Rows[1].Cells[0].Value = "Some Text";
Also as another option, you can handle CellFormatting event of your grid. This way may be useful when you want to set different texts for buttons.
void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
//If this is header row or new row, do nothing
if (e.RowIndex < 0 || e.RowIndex == this.dataGridView1.NewRowIndex)
return;
//If formatting your desired column, set the value
if (e.ColumnIndex=this.dataGridView1.Columns["dataGridViewDeleteButton"].Index)
{
e.Value = "Delete";
}
}
Handle Click Event of Button
To hanlde clicks on button, you can handle CellClick or CellContentClick event of your grid. Both events fires by click and by pressing Space key.
void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
//if click is on new row or header row
if( e.RowIndex == dataGridView1.NewRowIndex || e.RowIndex < 0)
return;
//Check if click is on specific column
if( e.ColumnIndex == dataGridView1.Columns["dataGridViewDeleteButton"].Index)
{
//Put some logic here, for example to remove row from your binding list.
//yourBindingList.RemoveAt(e.RowIndex);
// Or
// var data = (Product)dataGridView1.Rows[e.RowIndex].DataBoundItem;
// do something
}
}
Get data of the record on Click event
You have e.RowIndex, then you can get the data behind the row:
var data = (Product)dataGridView1.Rows[e.RowIndex].DataBoundItem;
// then you can get data.Id, data.Name, data.Price, ...
You need to cast it to the data type of the recore, for example let's say Product.
If the data binding has been setup to use a DataTable, the the type to cast is DataRowView.
You can also use dataGridView1.Rows[e.RowIndex].Cells[some cell index].Value to get value of a specific cell, however DataBoundItem makes more sense.
Note
As mentioned by Ivan in comments, when you use BindingList you don't need to set datasource of grid to null and back to binding list with every change. The BindingList itself reflects changes to your DataGridView.
I have gridcontrol that has a RepositoryLookupEdit in one of the columns. I can get the value of RepositoryLookupEdit after changed, but I dont know how to get the which row's RepositoryLookupEdit value changed. How can I get the Row ID?
With the code below, I can get the RepositoryLookupEdit value.
private void repositoryItemLookUpEdit1_EditValueChanged(object sender, EventArgs e)
{
LookUpEdit edit = sender as LookUpEdit;
var row = edit.Properties.GetDataSourceRowByKeyValue(edit.EditValue);
}
Since repositoryItemLookUpEdit isn't restricted to GridControls you cannot get the row handle from this event. You however have other possibilities.
First, if the edit is done by the user, you can use the ColumnView.GetFocusedRow() method to get the current grid row.
If however the edit value is changed via code it will also be changed in the grid so you can now use the ColumnView.CellValueChanged event.
private void repositoryItemLookUpEdit1_EditValueChanged(object sender, EventArgs e)
{
LookUpEdit edit = sender as LookUpEdit;
var row = edit.Properties.GetDataSourceRowByKeyValue(edit.EditValue);
gridRow = gridView.GetFocusedRow() as MyDataRow
}
Suppose if I say I have selected a row in gridview and want that row to come up in to their respective textboxes. For example, I have selected a row which has First Name and Last Names and on selection of row, the data from gridview should come in to textbox on winform. Please tell me.
I am guess it is something based on selection changed event if I am right ? Like below:
private void dgv_SelectionChanged(object sender, EventArgs e)
{
string str = txtFirstName.Text;
DataGridViewRow selectedRow;
}
If I got your question right, your solution is to use DataGridView.SelectedRows Property along with DataGridView.SelectionChanged Event
DataGridView.SelectedRows Gets the collection of rows selected by the
user.
DataGridView.SelectionChanged occurs whenever cells are selected or
the selection is canceled, whether programmatically or by user action.
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count > 0)
{
foreach (DataGridViewRow row in dataGridView1.SelectedRows) {
//Send the first cell value into textbox'
Txt_FirstName.Text = row.Cells(0).Value.ToString; // or row.Cells["ColumnName"].Value;
}
}
}
MSDN and MSDN