How can I highlight the row and current cell in a datagridview differently?
I have SelectionMode set to CellSelect and MultiSelect set to False.
I want the whole row to be highlighted and the selected cell to be highlighted in a different color. Basically something like this:
I'm trying to use the CellEnter event to do so with this code:
dgvResult.SelectedRows[0].DefaultCellStyle.SelectionBackColor = Color.LightBlue;
dgvResult.SelectedCells[0].Style.SelectionBackColor = Color.Blue;
dgvResult.Refresh();
Unfortunately the first line seems to only work when Selection Mode is set to FullRowSelect and the second row only works when set to CellSelect.
What am I doing wrong here?
This is a little trickier than one may hope.
You need to either keep track of the colors you set to the cells or reset all each time.
The latter is more reliable imo.
The DGV is in DataGridViewSelectionMode.FullRowSelect.
Note: Resetting a DefaultCellStyle Color is done by setting it to Color.Empty.
Example:
private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0) return;
foreach ( DataGridViewRow row in dataGridView1.SelectedRows)
row.DefaultCellStyle.SelectionBackColor = Color.Empty;
foreach ( DataGridViewCell cell in dataGridView1.SelectedCells)
cell.Style.SelectionBackColor = Color.Empty;
dataGridView1.Rows[e.RowIndex].DefaultCellStyle.SelectionBackColor = Color.RosyBrown;
dataGridView1[e.ColumnIndex, e.RowIndex].Style.SelectionBackColor = Color.LightSeaGreen;
}
Other events should also work..
Upddate:
As Jimi noted instead of resetting before setting in the same click event one can use the CellLeave event paired with the CellEnter event to do the same. Seems to work fine from my tests:
private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
dataGridView1.Rows[e.RowIndex].DefaultCellStyle.SelectionBackColor = Color.RosyBrown;
dataGridView1[e.ColumnIndex, e.RowIndex].Style.SelectionBackColor = Color.LightSeaGreen;
}
private void dataGridView1_CellLeave(object sender, DataGridViewCellEventArgs e)
{
dataGridView1.Rows[e.RowIndex].DefaultCellStyle.SelectionBackColor = Color.Empty;
dataGridView1[e.ColumnIndex, e.RowIndex].Style.SelectionBackColor = Color.Empty;
}
Related
I need to trim the cells in the DataGridView when it's populated with data.
I can't figure out how to call the CellFormatting event from within the DataBindingComplete Event. Surely it's as simple as;
private void iCBOMHDataGridView_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
iCBOMHDataGridView_CellFormatting();
}
I am doing something similar that might help. In my case, I am setting an inactive user's whole row to gray text, but it is still cell formatting:
dgvUsers.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.dgvUsers_CellFormatting);
this.Controls.Add(dgvUsers);
The lines above happen before you dgvUsers.Enabled = true; The grid has been loaded, but not displayed. Then the handler that gets called is:
private void dgvUsers_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataRowView row = dgvUsers.Rows[e.RowIndex].DataBoundItem as DataRowView;
if (row != null && row.Row.ItemArray[7].Equals("N"))
{
e.CellStyle.ForeColor = Color.Gray;
dgvUsers.Invalidate();
}
}
The main difference between the cell styling I do and yours is that I am not working with the actual values in the cells, just their styling.
I had a Gridview which contains 3 columns , initially during form load i only two columns will be visible one column will be having data and other having checkbox.
i want when i check a checkbox in particular cell, corresponding to that checkbox the third column cell will be visible, i don't want to complete 3rd column to get visible on checking a check box ,Gridview is hardcoded only rows are dymanic (column1,column2 are set to visible and column 3 is set to invisible)
in below inmage when i m checking checkbox complete thried column is visible,which i don't want
can any one help me in this?
i tried below code but it is making 3rd column visible not, particular cell
public form1()
{
dataGridView1.CellValueChanged += new DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
}
void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
dataGridView1.Columns[e.ColumnIndex + 1].Visible = true;
}
Well You can try RowCommand event for this but as i see you already have event created for checkbox ,Try to find row Index for particular row and then use Cell number (cell[2]) to find the control and assign its property as visible = false,
Here is the demo I've just tried. It seems to work OK. The whole idea is You can't hide a particular cell in DataGridView. However you can make it hidden as a normal GUI engine will use when it wants to hide any control/element (I think so). You just customize it to paint the cell with the BackgroundColor of your DataGridView. Of course, to make it work, it's not such easy. Here is the code for you:
//First, you have to be sure the whole third column is Visible.
//CellPainting event handler for your dataGridView1
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex == 2)//This is the Column index you want to hide.
{
object o = e.RowIndex == -1 ? null : dataGridView1[e.ColumnIndex - 1,e.RowIndex].Value;
if (o!=null &&!(bool)o || e.RowIndex == -1 || e.RowIndex == dataGridView1.RowCount - 1)
{
e.Graphics.FillRectangle(new SolidBrush(dataGridView1.BackgroundColor), e.CellBounds);
if(e.RowIndex > -1) dataGridView1[e.ColumnIndex, e.RowIndex].ReadOnly = true;
e.Handled = true;
}
if (o != null && (bool)o)
{
dataGridView1[e.ColumnIndex, e.RowIndex].ReadOnly = false;
}
}
}
//CellContentClick event handler for your dataGridView1
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
UpdateThirdColumCell(e);
}
//CellContentDoubleClick event handler for your dataGridView1
private void dataGridView1_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
{
UpdateThirdColumCell(e);
}
private void UpdateThirdColumCell(DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 1)//The column index of the CheckBox column
{
DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell)dataGridView1[e.ColumnIndex, e.RowIndex];
cell.Value = cell.EditingCellFormattedValue;
dataGridView1.Invalidate();
if ((bool)cell.Value)
{
dataGridView1.CurrentCell = dataGridView1[e.ColumnIndex + 1, e.RowIndex];
}
}
}
//CellStateChanged event handler for your dataGridView1
private void dataGridView1_CellStateChanged(object sender, DataGridViewCellStateChangedEventArgs e)
{
if (e.Cell.ColumnIndex == 2 && e.Cell.Selected)
{
dataGridView1.BeginEdit(false);
}
}
And that's all :)
Yeah ,actually we can't make invisible but i want to give an explianation about it in simple way.using
datagridview.rows(e.rowindex).cells[your column name]=true ;
using this it won't allow the user to enter the data in the textbox.if it is false then we can modify it/enter any text.
datagridview.rows(e.rowindex).cells[your column name].backcolour=color.gray/white/black;
using this we can fill color to a particular textbox which is to be painted when checkbox is true/false;
i'm trying to set a cell to edit mode. The cell is in the new row (NewRowIndex). Everwhere else it works well, but if i try to set the edit mode in the NewRowIndex, it doesn't get into edit mode as supposed. I simply want that i f user enters a new row (NewRowIndex), the first cell get into edit mode. I've tried (on RowEnter):
dgvList.CurrentCell = dgvList["myColName", dgvList.NewRowIndex]; dgvList.BeginEdit(true);
Thank you!
I dont think you really need to utilize the NewRowIndex property. Just begin edit by setting the current cell:
private void dgvList_CellEnter(object sender, DataGridViewCellEventArgs e)
{
dgvList.CurrentCell = dgvList[e.ColumnIndex, e.RowIndex];
dgvList.BeginEdit(true);
}
If you want the cell to go in edit mode only for new rows, then:
private void dgvList_CellEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex != dgvList.NewRowIndex)
return;
dgvList.CurrentCell = dgvList[e.ColumnIndex, e.RowIndex];
dgvList.BeginEdit(true);
}
Edit: If you want the new row to start being in edit mode upon keydown, then that's a feature already available for datagridviews. You can manually set it like this:
dgvList.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2;
//or
dgvList.EditMode = DataGridViewEditMode.EditOnKeystroke;
If you want the cell to be in edit mode upon keydown only for new rows, then you will have to override the default behaviour, by hooking KeyDown event, which I believe is a bad way f doing GUI. May be like this:
Initialize: dgvList.EditMode = DataGridViewEditMode.EditOnF2; //or whatever you prefer
to override the default excel style editing upon keystroke. And then
private void dgvList_KeyDown(object sender, KeyEventArgs e)
{
if (dgvList.CurrentCell.RowIndex != dgvList.NewRowIndex)
return;
dgvList.BeginEdit(true);
}
I want to initialize some of the rows of my DataGridView in red, base on a certain condition. The thing is, I've been playing around but I can't get this to work when the DataGridView is shown. . I try to do this in the constructor of the MainForm but no luck at all.
private void UpdateSoldOutProducts ()
{
for (int i = 0; i < productsTable.Rows.Count; i++)
if ((int)productsTable.Rows [i] ["Quantity"] == 0)
dataGridViewProducts.Rows [i].DefaultCellStyle.BackColor = Color.Red;
}
This method is calle in the constructor of the MainForm.
Try RowPostPaint event, it works for me :
private void dataGridViewProducts_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
if ((int)dataGridViewProducts.Rows[e.RowIndex].Cells["Quantity"].Value == 0)
dataGridViewProducts.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Red;
}
You can paint DataGridView Rows and Cells using Custom Painting. it is done with
the DataGridView.RowPostPaint Event and DataGridView.RowPrePaint Event.
The another expect is Paint Event.
private void dataGridViewProducts_Paint(object sender, PaintEventArgs e)
{
foreach (DataGridViewRow row in dataGridViewProducts.Rows)
{
int value = Convert.ToInt32(row.Cells["Quantity"].Value);
if (value == 0)
row.DefaultCellStyle.BackColor = Color.Red;
}
}
You can use DataGridViewRowPostPaintEventArgs or DataGridViewRowPrePaintEventArgs to set the Row or Cell style on the basis of condition..
You can handle this event alone or in combination with the RowPrePaint event to customize the appearance of rows in the control. You can paint entire rows yourself, or paint specific parts of rows and use the following methods of the DataGridViewRowPostPaintEventArgs class to paint other parts:
DrawFocus
PaintCells
PaintCellsBackground
PaintCellsContent
PaintHeader
Check this example on MSDN link and try to put you code one of these events.. here you you will get the Currrent row index using the DataGridViewRowPostPaintEventArgs
int value = Convert.ToInt32(dataGridViewProducts.Rows[e.RowIndex].Cells["Quantity"].Value);
if (value == 0)
dataGridViewProducts.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Red;
Edit:
Put you code on Form Load event or DataBinding Completed event. may this solve your problem.
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