Custom cell merged - c#

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.

Related

Custom column display text gets applied to cells it shouldn't

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...";
}
}
}

How to disable click on empty rows in DataGridView

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
}
}

Highlight the null value cells in RadGridView C#

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;
}
}
}

Compare 2 different columns in the datagridview

In my datagridview, four columns 1 & 2 are read only col 3 & 4 got number values. I want to compare that 4th column must be greater that 3rd column.
For example:
If the 4th column value is less than the 3rd column then I want to propose message doesn't navigate to another control.
My simple approach seems not working. How can I compare 2 specific columns for this kind of condition?
private void datagridview_CellValidating(object sender, CellValidatingEventArgs e)
{
try
{
int bbor = datagridview.CurrentCell.ColumnIndex;
int ebor = datagridview.CurrentCell.RowIndex;
if (ebor <= bbor)
{
MessageBox.Show("Please verify the value");
e.Cancel = true;
}
}
catch (Exception exception)
{
}
}
we meet again. Use the cell_click event:
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != 0)
{
if (Double.Parse(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString()) <= Double.Parse(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex - 1].Value.ToString()))
{
MessageBox.Show("Please verify the value");
}
}
}
EDIT 1: This seems to work fine, lemme know.
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
if (e.ColumnIndex != 0)
{
if (Double.Parse(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString()) <= Double.Parse(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex - 1].Value.ToString()))
{
MessageBox.Show("Please verify the value");
e.Cancel = true;
}
}
}
Edit 2: Updated for Telerik controls
private void radGridView1_CellValidating(object sender, Telerik.WinControls.UI.CellValidatingEventArgs e)
{
if (e.ColumnIndex != 0)
{
if (e.Value != null && radGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex - 1].Value != null)
{
if (Double.Parse(e.Value.ToString()) <= Double.Parse(radGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex - 1].Value.ToString()))
{
MessageBox.Show("error");
e.Cancel = true;
}
}
}
}
I'd see something more or less like that:
If you want to check all rows:
DataRow dr;
for(int i = datagridview.Rows.Count-1; i > 0; i--) {
dr = datagridview.Rows[i];
if(dr[e.ColumnIndex] > dr[e.ColumnIndex+1]){
//your message code
e.Cancel = true;
break; (or return;)
}
}
If you want to check only the current row where the cell is being edited:
DataRow dr = datagridview.Rows[e.RowIndex];
e.Cancel = dr[e.ColumnIndex] > dr[e.ColumnIndex+1];
if(e.Cancel)
//your message code
Maybe you will need to convert objects to int for comparison.
See the Rows Property for DataGridView http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.rows.aspx
this.dataGridView1[col, row].Value
references a specific cell for each row
foreach (Row r in this.dataGridView1.Rows) {
if (r.Cells[3].Value <= r.Cells[2].Value ) {
System.Console.WriteLine ("error");
}
}
For your validation check you'll want to use the FormattedValue property to see what value your user wants to insert in the cell they've edited. You can't use the current cell value because it doesn't update to the new value until after the CellValidating completes without DataGridViewCellValidatingEventArgs.Cancel being set to true.
Something like this:
private void datagridview_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) {
// This is the new proposed value the user entered; could be for column 3 or 4.
int newValue = int.Parse(e.FormattedValue.ToString());
// See which column fired the CellValidating event and use the new proposed value for it
// in place of the cell's actual value for purposes of our validation.
int col3Value = (e.ColumnIndex == 2) ? newValue : (int)dataGridView1[2, e.RowIndex].Value;
int col4Value = (e.ColumnIndex == 3) ? newValue : (int)dataGridView1[3, e.RowIndex].Value;
if (col3Value <= col4Value) {
MessageBox.Show("Please verify the value");
e.Cancel = true;
}
}
The code I show here is to demonstrate a solution to your problem. In your actual production code
you'll want to verify that casting from object to int is successful (through int.TryParse) or catch the exception that's raised when this operation fails. When this happens you can Cancel = true the cell validation and present to the user a message that he must enter a number.
And another quick note: don't use empty catch blocks (though I realize this probably isn't in your production code).

Problem with the DataTable and DataGridView objects

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;
}

Categories

Resources