I have a radGridView, the user inserts rows, i want to highlight the cell with null values. For example to make the back color of the cell Red.
I have tried the below code, but it did not work...
Inside a button
for (int j = 0; j < radGridView1.Rows.Count; j++)
{
if (radGridView1.Rows[j].Cells[4].Value.ToString() == "")
radGridView1.Rows[j].Cells[4].Style.ForeColor = Color.Red;
}
So how to do it? or if there is a better highlight method that notifies the user for the empty cell.
Thanks in advance
Fadddd,
I'll keep it clean and to the point:
03Usr's answer is talking about a row, you want individual cells
CyberDude's answer doesn't take into account the many events that Telerik's DGV has to modify appearance and functionality
With that said, your code seems to want to highlight empty values (null does not equal empty):
private void radGridView1_CellFormatting(object sender, CellFormattingEventArgs e)
{
if (e.RowIndex != -1)
{
if (e.CellElement.Value != null && e.CellElement.Value.ToString() == "")
{
radGridView1.Rows[e.CellElement.RowIndex].Cells[e.CellElement.ColumnIndex].Style.BackColor = Color.Red;
radGridView1.Rows[e.CellElement.RowIndex].Cells[e.CellElement.ColumnIndex].Style.CustomizeFill = true;
}
}
}
I do it in the ItemDataBound event, like this:
TableCell myCell = ((GridDataItem)e.Item)["ColumnName"];
...
myCell.ForeColor = Color.ForestGreen;
...
You can add OnRowDataBound="radGridView1_RowDataBound" to your gridview. This event gets triggered for every gridview row.
In the code behind you can have the following:
public void radGridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// do your highlighting here
if (e.Row.Cells[1].Value.ToString() == "")
{
e.Row.ForeColor = Color.Red;
}
}
}
Related
I got stuck while using the CustomColumnDisplayText Event. I am using this code:
private void gridView1_CustomColumnDisplayText(object sender, CustomColumnDisplayTextEventArgs e)
{
if (e.Column == colVehicle_FahrzeugartID && e.ListSourceRowIndex >= 0)
{
for (int i = 0; i < gridViewList.DataRowCount; i++)
{
object cellValue = gridViewList.GetRowCellValue(i, "Vehicle_FahrzeugartID");
this.clsFahrzeugart.ReadFromDb((int)cellValue);
if (this.clsFahrzeugart.Systemstatus == 11 && e.ListSourceRowIndex == i)
{
e.DisplayText = "Deleted...";
}
}
}
}
to display deleted if the value Systemstatus is 11 which stands for deleted in my database and everything works fine but if I am toggling my switch there are empty values in my column and some values are getting changed to deleted although they dont have the value 11.
This is how it looks if the Switch is toggled:
And this is how it should look like:
bool isOn = toggleSwitch1.EditValue is bool ? (bool)toggleSwitch1.EditValue : false;
if (isOn)
{
tbAutoBindingSource1.Filter = "Vehicle_Systemstatus = 1";
btn_UnDel.Visible = false;
}
else
{
tbAutoBindingSource1.Filter = "Vehicle_Systemstatus IS NOT NULL";
btn_UnDel.Visible = true;
}
Does somebody know how to fix this?
You do not need to traverse through all rows since this event is raised for an individual row. Since this event provides the e.ListDataSourceRowIndex property associated with a datasource row index, not a row handle, you need to use the GridView.GetListSourceRowCellValue method to access a cell value.
Refer to the Rows help topic to learn differences between datasource indexes and grid row handles.
private void gridView1_CustomColumnDisplayText(object sender, CustomColumnDisplayTextEventArgs e)
{
GridView view = sender as GridView;
if (e.Column == colVehicle_FahrzeugartID && e.ListSourceRowIndex >= 0)
{
object cellValue = view.GetListSourceRowCellValue(e.ListSourceRowIndex, "Vehicle_FahrzeugartID");
this.clsFahrzeugart.ReadFromDb((int)cellValue);
if (this.clsFahrzeugart.Systemstatus == 11)
e.DisplayText = "Deleted...";
}
}
You have several mistakes in your code.
0. Pointless cycle in event.
The CustomColumnDisplayText event are used to display text in currently processed cell. So, all you need is to get values according to that cell.
1. Wrong using of GetRowCellValue method.
You need to use RowHandle for GetRowCellValue. ListSourceRowIndex is wrong here. RowHandle and ListSourceRowIndex are not the same. You need to use GetRowHandle method to get RowHandle from ListSourceRowIndex.
Here is example:
private void gridView1_CustomColumnDisplayText(object sender, CustomColumnDisplayTextEventArgs e)
{
if (e.Column == colVehicle_FahrzeugartID && e.ListSourceRowIndex >= 0)
{
int rowHandle = gridViewList.GetRowHandle(e.ListSourceRowIndex);
object cellValue = gridViewList.GetRowCellValue(rowHandle, "Vehicle_FahrzeugartID");
this.clsFahrzeugart.ReadFromDb((int)cellValue);
if (this.clsFahrzeugart.Systemstatus == 11)
{
e.DisplayText = "Deleted...";
}
}
}
I need to display data in gridview with merged rows for some columns.
the original data from database like:
please help me to display gridview like:
for column transaksi merged by tgl
for column priority , price , creted by merged by transaksi
Using C#, how can I prepare a gridview for the format? Please help me.
I suggest you to go through documentation - Tutorial: Cell Merging
To implement custom cell merge use the GridView.CellMerge event
handler. First, check if the correct column is being processed. Then,
obtain display texts for the two cells being compared. Finally,
indicate that cells are to be merged if their display texts match. Set
the CellMergeEventArgs.Handled parameter to true to override the
grid's default processing for this column.
Example:
using DevExpress.XtraGrid.Views.Grid;
// ...
private void gridView1_CellMerge(object sender, DevExpress.XtraGrid.Views.Grid.CellMergeEventArgs e) {
GridView view = sender as GridView;
if(view == null) return;
if (e.Column == colCreatorID) {
string text1 = view.GetRowCellDisplayText(e.RowHandle1, colCreatorID);
string text2 = view.GetRowCellDisplayText(e.RowHandle2, colCreatorID);
e.Merge = (text1 == text2);
e.Handled = true;
}
}
Use your own conditions while processing a column. for example take transaksi 005, In this case check values of row 5 and 6 then compare column created by for equality depends upon your condition set the e.Merge to true.
I just picked response posted on this topic and added one line to achieve what you want.
bool IsTheSameCellValue(int column, int row)
{
// To compare only values on 1st and 2nd column (TGL, TRANSAKSI)
if (column > 1) return false;
DataGridViewCell cell1 = dataGridView[column, row];
DataGridViewCell cell2 = dataGridView[column, row - 1];
if (cell1.Value == null || cell2.Value == null)
{
return false;
}
return cell1.Value.ToString() == cell2.Value.ToString();
}
private void dataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None;
if (e.RowIndex < 1 || e.ColumnIndex < 0)
return;
if (IsTheSameCellValue(e.ColumnIndex, e.RowIndex))
{
e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None;
}
else
{
e.AdvancedBorderStyle.Top = dataGridView.AdvancedCellBorderStyle.Top;
}
}
private void dataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.RowIndex == 0)
return;
if (IsTheSameCellValue(e.ColumnIndex, e.RowIndex))
{
e.Value = "";
e.FormattingApplied = true;
}
}
However it's impossible to center text vertically in merged cells with this solution because it only erases the borders and not totally redraw the component.
How can I disable click/cursor on empty rows in DataGridView? I've alternating rows, one with data and another empty then row with data and then an empty row. I want to disable click on empty/null rows only.
I've improved my code thanks to breeze and partly got what i wanted to but this obviously applies to every cell. How can I implement this code so that ReadOnly Mode is true to only completely empty rows and not to those rows which has even a single cell containing data.
private void dataGridView3_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0)
{
return;
}
var dataGridView = (sender as DataGridView);
try
{
int col = e.ColumnIndex;
int row = e.RowIndex;
var cell = ((DataGridView)sender)[col, row];
if (cell != null && cell.Value != "")
{
dataGridView.Cursor = Cursors.Hand;
}
else
{
dataGridView.Cursor = Cursors.No;
dataGridView.ReadOnly = true;
}
}
catch (Exception es)
{
MessageBox.Show(es.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
Thanks for your help..
The trick is to not only check if the reference to the cell is empty but also if the value of the cell is an empty string. To do this you expand
if(cell != null)
to
if(cell != null && cell.Value != "")
The check if cell is null is not really neccessary but it does no harm and protects you against some errors that could happen in further development.
This should get you there. This may need to be adjusted for your instance, and likely you should use "!=" to remove a few lines from the structure.
internal void AllRows_OnClick(object sender, EventArgs e){
int rowIndex = e.RowIndex;//Get Row that was clicked
DataGridViewRow row = dataGridView1.Rows[rowIndex];//update to Row
if (row.Cells[1].Value.ToString() == ""){
//Do Nothing
}else{
//Do Something
}
}
I have the following problem
In my aplication I doing some calculations and after it put them into DataTable object (6 columns, data in the latest one is most important). To view the results I put them into DataGridView object and there is my problem. Depending on the data contained in the last column I want to mark the cells on the appropriate colors. And I don't know if I should do this on the DataGridView object because this is user interfaces? Where I can do this? DataTable object doesn't have a style properties?
Thanks a lot...
You can use the CellPainting event of the DataGridView to format your cells based on their content.
e.g. `
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
{
switch (dataGridView1.Columns[e.ColumnIndex].DataPropertyName)
{
case "Description":
{
break;
}
case "NormalRoom":
{
break;
}
case "Colour1":
case "Colour2":
{
Color co = Color.White;
if (e.Value != null && e.Value != DBNull.Value)
{
co = string2Color((string)e.Value);
}
e.CellStyle.BackColor = Color.White;
e.CellStyle.ForeColor = Color.Black;
etc.`
I've done simething like this:
public void setABCColor(DataGridView DGV)
{
for (int i = 0; i < DGV.Rows.Count; i++)
{
if ((string)DGV.Rows[i].Cells[6].Value == "A")
{
DGV.Rows[i].Cells[6].Style.BackColor = Color.Green;
}
else if ((string)DGV.Rows[i].Cells[6].Value == "B")
{
DGV.Rows[i].Cells[6].Style.BackColor = Color.Blue;
}
else
{
DGV.Rows[i].Cells[6].Style.BackColor = Color.Red;
}
}
}
Is this acceptable? Is this not change the assumption of the MVC design pattern?
I would recommend putting the logic in the Cell Formatting event of the datagridview.
These would also reflect changes in case your data changes dynamically based on some calculations in the grid
something like
void myDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.Value.ToString() == "A" )
e.CellStyle.BackColor = Color.Red;
}
I have a checkbox column in a DataGridView and I want to validate whether the user can check a checkbox by counting the number of checkboxes they click and deciding
then to disable checking.
Can someone guide me how to do this effectively??
Quick code sample:
public partial class DGVCheckBoxTesting : Form
{
private const int MAX_CHECKS = 5;
public DGVCheckBoxTesting()
{
InitializeComponent();
this.dataGridView1.Columns.Add("IntColumn", "IntColumn");
this.dataGridView1.Columns.Add(new DataGridViewCheckBoxColumn { Name = "BoolColumn" });
for (int i = 0; i <= 10; i++)
{
this.dataGridView1.Rows.Add(i, false);
}
this.dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);
this.dataGridView1.CellContentDoubleClick += new DataGridViewCellEventHandler(dataGridView1_CellContentDoubleClick);
}
private void dataGridView1_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
{
this.ValidateCheckBoxState(e);
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
this.ValidateCheckBoxState(e);
}
private void ValidateCheckBoxState(DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != 1) //bool column
{ return; }
this.dataGridView1.EndEdit();
bool value = (bool)this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
int counter = 0;
foreach (DataGridViewRow row in this.dataGridView1.Rows)
{
if (row.Cells[1].Value != null && (bool)row.Cells[1].Value)
{
counter++;
}
}
if (counter > MAX_CHECKS)
{
this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = false;
this.dataGridView1.EndEdit();
}
}
}
Basically, what this code does is it adds an Integer column and a Bool column to the DataGridView. Then, on the CellContentClick event, if the checkbox column was clicked, first we commit the edit (if you don't do this, you'll have all kinds of trouble figuring out if the checkbox is checked or not). Then, we loop through the rows and count all the checked rows. Then, if the amount is greater than what we want to allow, we just set it back to false, and again re commit the edit. Test it out, it works. May not be the most elegant solution, but the DGV can be tricky with the checkboxes, so this is how I would do it.
EDIT: Just a small edit, I hooked into the ContentDoubleClick event as well, as I noticed you were able to beat the validation if you quickly clicked on the cell. Should work better now.