I am using DataGridView CellFormating to format specified cells.
The code I am trying:
private void dgwPart_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (this.arts.Type == ArtType.Pak)
{
if (dgwPart.Columns[e.ColumnIndex].Name == "Discount")
e.Value = "";
}
}
The problem is that it changes the value for all column, but I only want that it changes the value for specified row. How do I manage it?
You can use e.CurrentCell to find whether it is the row you want, something like:
If (dvImages.CurrentCell.RowIndex == 10)
{
Debug.WriteLine("Do something")
}
If ((int)(dvImages.CurrentCell.Value) = 100)
{
...
}
* these should be within the cellformat, after you check the column.
you may need check the syntax, I just typed this from my header.
Related
I tried
int A = DataGridView1.Rows[0].Cells[3].value
and
int A = (int)DataGridView1.Rows[0].Cells[3].value
or using Cast or Parse method but it doesn't work.
You shouldn't be doing any of these things.
Your DataGridView should be databound (databind'd) to a DataTable that has a fourth column that is an integer or to a list of objects that has a property that appears in the fourth column of the datagridview, that is an integer:
var x = (int)myDataTableThatTheDGVIsBoundTo.Rows[0][3];
var x = myListOfPeopleWhereAgeAppearsAsDGVFourthColumn[0].Age;
DataGridView is intended for VIEWing a model of data that is kept elsewhere. If you want data out of the model, you get it from the model, not the view. If you want to know something that is eg what the user selected in the view, or is the current row etc you either retrieve the relevant model rows from the SelectedCell's OwningRow.DataBoundItem or use something like a bindingsource that understand sthe concept of "current row"
To really answer this we need a lot more info about how your data got into your grid in the first place. I get the feeling it's not in a model at all :/
try
{
string cellValue = DataGridView1.Rows[0].Cells[3].Value.ToString();
int intCellValue = System.Convert.ToInt32(cellValue);
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
The try-catch block is used in case the user somehow inserted a non-integer value in the datagrid.
Something like that will work too.
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
e.Control.KeyPress -= new KeyPressEventHandler(Column1_KeyPress);
if (dataGridView1.CurrentCell.ColumnIndex == 0) //Desired Column
{
TextBox tb = e.Control as TextBox;
if (tb != null)
{
tb.KeyPress += new KeyPressEventHandler(Column1_KeyPress);
}
}
}
private void Column1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
Found this code sample on another thread.
dgwProducts.Rows[0].Cells[3].Value
return object.
You can this:
int A = Convert.ToInt32(dgwProducts.Rows[0].Cells[3].Value.ToString());
I have a cell in datagridview in which I display time in a custom format. I need when used enters edit mode (for example by double-click), I need to change the string value to integer representing the time in minutes.
When I try to change the cell value in "CellEnter" event, it doesn't seem to respond. Actually it doesn't seem to change the cell value pretty much inside any event.
Please don't mind the details of converting time to string and vise versa, my question is how can I successfully change the content of a cell when user double-clicks on it.
Edit (code + solution):
What I did is use another column to store the actual value (without formatting). On cell formatting of that column I'm passing the value to custom format function to fill my column.
private void gridview_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
if (e.ColumnIndex == 3 && e.Value != null && e.Value.ToString() != "")
{
//fill the unbound textbox column (5) from raw value column (3)
string newValue = TimeAttendanceHelper.FormatHourlyDuration(e.Value);
gridview.Rows[e.RowIndex].Cells[5].Value = newValue;
}
}
And then thanks to TaW, on CellBeginEdit I am showing the raw value to edit it:
private void gridview_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if (e.ColumnIndex == 5)
{
//on editing, use the value from raw data column (3)
gridview.Rows[e.RowIndex].Cells[5].Value = gridview.Rows[e.RowIndex].Cells[3].Value;
}
}
And Finally when CellEndEdit, I reformat the new value:
private void gridview_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 4)
{
//update value both in columns 3 & 5
string newValue = tIME_SHIFTDataGridView.Rows[e.RowIndex].Cells[4].Value.ToString();
gridview.Rows[e.RowIndex].Cells[3].Value = newValue;
gridview.Rows[e.RowIndex].Cells[4].Value = TimeAttendanceHelper.FormatHourlyDuration(newValue);
}
}
When the cell is in edit mode you need to change the text in the edit control, usually a Textbox. You can get (and hold) a handle to it in the EditingControlShowing event:
TextBox editBox = null;
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
if (e.Control is TextBox) editBox = e.Control as TextBox;
}
But using the CellEnter event is not a good idea as it will be called when scrolling or clicking around as well..
To catch the beginning of editing you use the BeginEdit event:
int yourEditColumn = 5;
private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if (e.ColumnIndex == yourEditColumn )
{
string yourValue = "12345";
dataGridView1.Rows[e.RowIndex].Cells[yourEditColumn ].Value = yourValue;
if (editBox != null) editBox.Text = yourValue;
}
}
I have a datagridview with multiple checkboxes. When the Finished checkbox is checked I need to execute linq code to update a specific table. How do I find out if that specific check box is dirty and where do I write the code to pass the values I need to be passed to the table. Note that it is not the same table that the datagridview is based on.
Thanks.
EDIT:
private void propertyInformationDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
DataGridViewCheckBoxCell checkCell = (DataGridViewCheckBoxCell)propertyInformationDataGridView.Rows[e.RowIndex].Cells[3];
DataGridViewRow row = propertyInformationDataGridView.Rows[e.RowIndex] as DataGridViewRow;
System.Data.DataRowView SelectedRowView;
newCityCollectionDataSet.PropertyInformationRow SelectedRow;
SelectedRowView = (System.Data.DataRowView)propertyInformationBindingSource.Current;
SelectedRow = (newCityCollectionDataSet.PropertyInformationRow)SelectedRowView.Row;
if (Convert.ToBoolean(checkCell.EditedFormattedValue) == true)
{
DataClasses1DataContext dc = new DataClasses1DataContext();
var matchedCaseNumber = (from c in dc.GetTable<PropertyInformation>()
where c.CaseNumberKey == SelectedRow.CaseNumberKey
select c).SingleOrDefault();
reportsSent newReport = new reportsSent();
newReport.CaseNumberKey = SelectedRow.CaseNumberKey;
dc.reportsSents.InsertOnSubmit(newReport);
dc.SubmitChanges();
}
}
Do I need to endedit at some point is that the issue?
This is from some of my code, all you need to do is create a "CellContentClick" event for your datagridview.
The easiest way to do this is select the Datagridview, go to properties and click on the lightning bolt. Scroll down to "CellContentClick" and double click in the empty box. This will auto generate the method you need to paste the following code into.
Make sure you rename my instances of "CustomersDataGridView" to whatever yours is named as well, intellisense should highlight invalid code in red that you need to replace.
Also, the "9" you see in the checkCell declaration needs to be changed to the index of your "Finished" check-box. If it is in the 3rd cell from the left, put a 2 there instead of a 9, as the indexing is 0 based.
EDITTED to fix comments:
private void CustomersDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex.ToString() == "9")
{
DataGridViewCheckBoxCell checkCell = (DataGridViewCheckBoxCell)CustomersDataGridView.Rows[e.RowIndex].Cells[9];
DataGridViewRow row = CustomersDataGridView.Rows[e.RowIndex] as DataGridViewRow;
if (Convert.ToBoolean(checkCell.EditedFormattedValue) && CustomersDataGridView.IsCurrentCellDirty)
{
//Do Work here.
var z = row.Cells[0].Value; // Fill in the brackets with the column you want to fetch values from
//z in this case would be the value of whatever was in the first cell in the row of the checkbox I clicked
}
}
}
You can do it in the CheckedChanged-Event
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
// Do what you have to do...
}
How to change DataGridView cell ForeColor based on whether new cell value is > or < than current/old cell value? Is there an event which passes the new value before the current is changed, so I can compare them?
The data is updated from underlying source, and may be bound by BindingSource.
I ran into a similar issue. I tackled this by using the CellValidating event instead:
void dgv_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
var oldValue = dgv[e.ColumnIndex, e.RowIndex].Value;
var newValue = e.FormattedValue;
}
Admittedly, I just needed access to the old value, I didn't need to perform any formatting. I'm sure you can apply formatting through this event handler, though.
If the inner source of DataGridView control is a DataTable then you can utilize the older version of DataRow using DataRowVersion enum. Note that I have utilized CellFormatting Event.
Example:
private void DataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
// if NOT the DataGridView's new row
if (!this.dataGridView1.Rows[e.RowIndex].IsNewRow)
{
// if my desired column
if (e.ColumnIndex == 0)
{
TestDataSet.TestRow row;
row = (TestDataSet.TestRow)((DataRowView)this.dataGridView1.Rows[e.RowIndex].DataBoundItem).Row;
if (row.Column1, (int)row["Column1", DataRowVersion.Original]) > 0)
e.CellStyle.ForeColor = Color.Red;
}
}
}
You may want to look at the DataGridView.CellValueChangedevent (http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.cellvaluechanged.aspx).
If you want to check the value before it is saved, then look at DataGridView.CurrentCellDirtyStateChanged (http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged.aspx).
You can store the old value of the cell in a variable, to compare and change the ForeColor depending on the result, then delete the old value from the variable.
Regards.
private double CuerrLineQty;
private void GridTransaction_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
if (currOp != CurrentOperation.FillDone)
return;
CuerrLineQty = double.Parse(GridTransaction.Rows[e.RowIndex].Cells["DisplayQty"].Value.ToString());
CuerrLineQty = double.Parse(GridTransaction.Rows[e.RowIndex].Cells["DisplayQty"].FormattedValue.ToString());
CuerrLineQty = double.Parse(GridTransaction.Rows[e.RowIndex].Cells["DisplayQty"].EditedFormattedValue.ToString());
}
screenshot
I added datagridview to my win forms app and I also added one CheckBox for marking rows.
The CheckBox works as I expected until the user sorts the DataGridView. After the sort the previous selection of checkbox column is lost.
Is there a way I can make my datagridview remember which row is selected after sorting?
You have two options to solve this issue.
The first and possibly the most simple is to bind your checkbox column to your datasource. For example, if you are using a DataTable as your datasource, adding a boolean column will create a checkbox on your DataGridView that will sort and not lose the checked state.
If this is not an option then the other way of addressing the problem is to set your DataGridView to Virtual mode and maintain a cache of your checkbox values.
Check out the excellent DataGridView FAQ for an example of how to do this. I've also provided the code below but do check out the FAQ:
private System.Collections.Generic.Dictionary<int, bool> checkState;
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.AutoGenerateColumns = false;
dataGridView1.DataSource = customerOrdersBindingSource;
// The check box column will be virtual.
dataGridView1.VirtualMode = true;
dataGridView1.Columns.Insert(0, new DataGridViewCheckBoxColumn());
// Initialize the dictionary that contains the boolean check state.
checkState = new Dictionary<int, bool>();
}
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
// Update the status bar when the cell value changes.
if (e.ColumnIndex == 0 && e.RowIndex != -1)
{
// Get the orderID from the OrderID column.
int orderID = (int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;
checkState[orderID] = (bool)dataGridView1.Rows[e.RowIndex].Cells[0].Value;
}
}
private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
// Handle the notification that the value for a cell in the virtual column
// is needed. Get the value from the dictionary if the key exists.
if (e.ColumnIndex == 0)
{
int orderID = (int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;
if (checkState.ContainsKey(orderID))
e.Value = checkState[orderID];
else
e.Value = false;
}
}
private void dataGridView1_CellValuePushed(object sender, DataGridViewCellValueEventArgs e)
{
// Handle the notification that the value for a cell in the virtual column
// needs to be pushed back to the dictionary.
if (e.ColumnIndex == 0)
{
// Get the orderID from the OrderID column.
int orderID = (int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;
// Add or update the checked value to the dictionary depending on if the
// key (orderID) already exists.
if (!checkState.ContainsKey(orderID))
{
checkState.Add(orderID, (bool)e.Value);
}
else
checkState[orderID] = (bool)e.Value;
}
}
I'm surprised that that happens, but if there's no other way around it in a worst case you could set the sorting to programmatic and then handle when the user clicks on the column header, save a list of which items are checked, do the sorting programmatically and then check any items that should be checked.