1) It is possible to change datagrid colors cell by cell, yes; 2) Not
Yet but By using reflection and capturing FeildInfo from the datagrid you can
change the colors. It's baised off of Alex Fienamn's alternating rows. I
added columns and a buffer. I also added code to check based upon the data
of the visible rows displayed to the user. This means it doesnt color 2000
rows in the table but only the 15 that are visible to the user.
I dont have a website to host it on yet but if anyone would be so kind to
post it and add the website to the post I would be happy to give your site
some buisness.
Please email-me: (e-mail address removed)
using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
namespace ModifiedDataColors
{
/// <summary>
/// Summary description for DataGridEvenOddHandler.
/// </summary>
class DataGridEvenOddHandler: IDisposable
{
private int myStart=0;
private int myStop=0;
private bool[] myBool = new bool[20];
private DataGrid m_grid;
private object m_r;
private Color[] arrClr = new Color[] { Color.Cyan, Color.LightYellow };
private Color[] arrClrText = new Color[] { Color.Black, Color.Black };
private SolidBrush brCell, brCellFore;
private FieldInfo m_fiRowVisibleFirst, m_fiRowVisibleLast,
m_fiColVisibleFirst, m_fiColVisibleLast;
private FieldInfo m_fiRowDrawFirst, m_fiRowDrawLast, m_fiColDrawFirst,
m_fiColDrawLast;
private FieldInfo m_fiRows;
private MethodInfo m_miDrawCells;
private DataGridCell currentCell;
DBAccess myData = new DBAccess();
private int iRowVisibleFirst, iRowVisibleLast, iColVisibleFirst,
iColVisibleLast;
private int RowIndex = -1;
public DataGridEvenOddHandler(DataGrid grid)
{
m_grid = grid;
HookGrid();
}
public void HookGrid()
{
System.Type myType = m_grid.GetType();
m_r = myType.GetField("m_renderer").GetValue(m_grid);
m_r = typeof(DataGrid).GetField("m_renderer",
BindingFlags.GetField).GetValue(m_grid);
m_r = typeof(DataGrid).GetField("m_renderer",
BindingFlags.Instance).GetValue(m_grid);
m_fiRowDrawFirst = m_r.GetType().GetField("m_irowDrawFirst",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
m_fiRowDrawLast = m_r.GetType().GetField("m_irowDrawLast",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
m_fiColDrawFirst = m_r.GetType().GetField("m_icolDrawFirst",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
m_fiColDrawLast = m_r.GetType().GetField("m_icolDrawLast",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
m_fiRowVisibleFirst = typeof(DataGrid).GetField("m_irowVisibleFirst",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
m_fiRowVisibleLast = typeof(DataGrid).GetField("m_irowVisibleLast",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
m_fiColVisibleFirst = typeof(DataGrid).GetField("m_icolVisibleFirst",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
m_fiColVisibleLast = typeof(DataGrid).GetField("m_icolVisibleLast",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
m_fiRows = typeof(DataGrid).GetField("m_rlrow",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
m_miDrawCells = m_r.GetType().GetMethod("_DrawCells",
BindingFlags.NonPublic|BindingFlags.Instance);
brCell = (SolidBrush )m_r.GetType().GetField("m_brushCellBack",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance).GetValue(m_r);
brCellFore = (SolidBrush )m_r.GetType().GetField("m_brushCellFore",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance).GetValue(m_r);
VScrollBar vsb = (VScrollBar)typeof(DataGrid).GetField("m_sbVert",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance).GetValue(m_grid);
HScrollBar hsb = (HScrollBar)typeof(DataGrid).GetField("m_sbHorz",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance).GetValue(m_grid);
vsb.ValueChanged += new EventHandler(vsb_ValueChanged);
hsb.ValueChanged += new EventHandler(hsb_ValueChanged);
m_grid.Paint += new PaintEventHandler(grid_Paint);
m_grid.CurrentCellChanged += new EventHandler(grid_CurrentCellChanged);
currentCell = m_grid.CurrentCell;
iRowVisibleFirst = (int)m_fiRowVisibleFirst.GetValue(m_grid);
iRowVisibleLast = (int)m_fiRowVisibleLast.GetValue(m_grid);
iColVisibleFirst = (int)m_fiColVisibleFirst.GetValue(m_grid);
iColVisibleLast = (int)m_fiColVisibleLast.GetValue(m_grid);
}
public void UnhookGrid()
{
if ( m_grid == null )
return;
VScrollBar vsb = (VScrollBar)typeof(DataGrid).GetField("m_sbVert",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance).GetValue(m_grid);
HScrollBar hsb = (HScrollBar)typeof(DataGrid).GetField("m_sbHorz",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance).GetValue(m_grid);
vsb.ValueChanged -= new EventHandler(vsb_ValueChanged);
hsb.ValueChanged -= new EventHandler(hsb_ValueChanged);
m_grid.Paint -= new PaintEventHandler(grid_Paint);
m_grid.CurrentCellChanged -= new EventHandler(grid_CurrentCellChanged);
}
public Color OddRowColor
{
get { return arrClr[1]; }
set { arrClr[1] = value;}
}
public Color EvenRowColor
{
get { return arrClr[0]; }
set { arrClr[0] = value;}
}
public Color OddRowTextColor
{
get { return arrClrText[1]; }
set { arrClrText[1] = value; }
}
public Color EvenRowTextColor
{
get { return arrClrText[0]; }
set { arrClrText[0] = value;}
}
private void ForceRepaintGridRow(Graphics g, int row)
{
/*
brCell.Color = arrClr[row % 2];
brCellFore.Color = arrClrText[row % 2];
m_fiRowDrawFirst.SetValue(m_r, row);
m_fiRowDrawLast.SetValue(m_r, row);
m_miDrawCells.Invoke(m_r, new object[] { g });
*/
if(((DataTable)m_grid.DataSource).TableName=="product")
{
if(myBool[row%20]==true) // CHANGE ONLY VISIBLE (THE FIRST 20 RECORDS)
ColorCell(row, g);
else
myBool[row%20]=CheckDeal(row,g);
CheckEnough(row, g);
}
}
private void ForceRepaintGridRows( Graphics g, int rowStart, int rowEnd )
{
if(rowEnd>0)
{
// I had multiple table display but I only wanted my product table to
have colors
if(((DataTable)m_grid.DataSource).TableName=="product")
for ( int i = rowStart; i <= rowEnd; i++ )
{
/*
brCell.Color = arrClr[i % 2];
brCellFore.Color = arrClrText[i % 2];
m_fiRowDrawFirst.SetValue(m_r, i);
m_fiRowDrawLast.SetValue(m_r, i);
m_miDrawCells.Invoke(m_r, new object[] { g });
*/
if(myStart==rowStart && rowEnd==myStop)
{
// Assume the visible rows are less than 20 so make a buffer
// so it doesnt have to recalculate & refresh the display.
if(myBool[i%20]==true)
ColorCell(i, g);
}
else
myBool[i%20]=CheckDeal(i,g);
// Doing calculations for the 20 items visible much
// faster than 2000 items in the table
CheckEnough(i, g);
}
myStart=rowStart;
myStop=rowEnd;
}
}
private void ForceRepaintGridRows( Graphics g, int [] range )
{
foreach ( int i in range )
{
/*
brCell.Color = arrClr[i % 2];
brCellFore.Color = arrClrText[i % 2];
m_fiRowDrawFirst.SetValue(m_r, i);
m_fiRowDrawLast.SetValue(m_r, i);
m_miDrawCells.Invoke(m_r, new object[] { g });
*/
if(((DataTable)m_grid.DataSource).TableName=="product")
{
if(myBool[i%20]==true)
ColorCell(i, g);
}
else
myBool[i%20]=CheckDeal(i,g);
CheckEnough(i, g);
}
}
private void vsb_ValueChanged(object sender, EventArgs e)
{
int iRowFirst = (int)m_fiRowVisibleFirst.GetValue(m_grid);
int iRowLast = (int)m_fiRowVisibleLast.GetValue(m_grid);
Graphics g = m_grid.CreateGraphics();
if ( iRowVisibleFirst > iRowFirst ) //Scroll Up
{
ForceRepaintGridRows(g, iRowFirst, iRowVisibleFirst);
}
else
{
ForceRepaintGridRows(g, iRowVisibleLast, iRowLast);
}
iRowVisibleFirst = iRowFirst;
iRowVisibleLast = iRowLast;
}
private void hsb_ValueChanged(object sender, EventArgs e)
{
grid_Paint(null, null);
}
#region IDisposable Members
public void Dispose()
{
UnhookGrid();
}
#endregion
private void grid_Paint(object sender, PaintEventArgs e)
{
repaintGrid();
}
public void repaintGrid()
{
int rowFirst, rowLast;
rowFirst = (int)m_fiRowVisibleFirst.GetValue(m_grid);
rowLast = (int)m_fiRowVisibleLast.GetValue(m_grid);
rowFirst = Math.Max(rowFirst, 0);
rowLast = Math.Max(rowLast, 0);
Color cl = brCell.Color;
Color clText = brCellFore.Color;
Graphics g;
g = m_grid.CreateGraphics();
ForceRepaintGridRows(g, rowFirst, rowLast);
brCell.Color = cl;
brCellFore.Color = clText;
}
private void grid_CurrentCellChanged(object sender, EventArgs e)
{
if(((DataTable)m_grid.DataSource).TableName.Equals("product"))
{
Color cl = brCell.Color;
Color clText = brCellFore.Color;
Graphics g = m_grid.CreateGraphics();
int nFirstVisibleRow = (int)m_fiRowVisibleFirst.GetValue(m_grid);
ArrayList Rows = (ArrayList) m_fiRows.GetValue(m_grid);
object Row;
FieldInfo fiSelected = Rows[0].GetType().GetField("m_fSelected",
BindingFlags.NonPublic|BindingFlags.GetField|BindingFlags.Instance);
if ( RowIndex > -1 )
{
Row = Rows[RowIndex];
if ( (bool)fiSelected.GetValue(Row) )
m_grid.Invalidate(_GetRowBounds(RowIndex));
else
ForceRepaintGridRow(g, RowIndex);
}
currentCell = m_grid.CurrentCell;
RowIndex = m_grid.CurrentRowIndex;
if ( RowIndex > -1 )
{
Row = Rows[RowIndex];
if ( (bool)fiSelected.GetValue(Row) )
m_grid.Invalidate(_GetRowBounds(RowIndex));
else
ForceRepaintGridRow(g, RowIndex);
}
brCell.Color = cl;
brCellFore.Color = clText;
}
}
private Rectangle _GetRowBounds(int iRow)
{
int colFirst = (int)m_fiColVisibleFirst.GetValue(m_grid);
int colLast = (int)m_fiColVisibleLast.GetValue(m_grid);
Rectangle r = m_grid.GetCellBounds(iRow, colFirst);
for ( int i = colFirst; i <= colLast; i++ )
{
Rectangle rNew = m_grid.GetCellBounds(iRow, i);
r.X = Math.Min(r.X, rNew.X);
r.Width = Math.Max(r.Right, rNew.Right) - Math.Min(r.X, rNew.X);
}
return r;
}
private void CheckEnough(int row, Graphics g)
{
// ONLY CHECK Column 7 & 8
for(int col=7; col<=8; col++)
{
if(int.Parse(m_grid[row, col].ToString())>int.Parse(m_grid[row,
col+7].ToString()))
{
brCellFore.Color=Color.Black;
brCell.Color=Color.Blue;
m_fiColDrawFirst.SetValue(m_r, col);
m_fiColDrawLast.SetValue(m_r, col);
m_fiRowDrawFirst.SetValue(m_r, row);
m_fiRowDrawLast.SetValue(m_r, row);
m_miDrawCells.Invoke(m_r, new object[] { g });
brCellFore.Color=Color.Black;
brCell.Color=Color.White;
m_fiColDrawFirst.SetValue(m_r, 0);
m_fiColDrawLast.SetValue(m_r, 0);
m_fiRowDrawFirst.SetValue(m_r, 0);
m_fiRowDrawLast.SetValue(m_r, 0);
m_miDrawCells.Invoke(m_r, new object[] { g });
}
}
}
private bool CheckDeal(int row, Graphics g)
{
if(CheckDealLevel(m_grid, row)==true)
{
ColorCell(row, g);
return true;
}
else
return false;
}
private void ColorCell(int row, Graphics g)
{
myBool[row % 20]=true;
brCellFore.Color=Color.Black;
brCell.Color=Color.Red;
m_fiColDrawFirst.SetValue(m_r, 5);
m_fiColDrawLast.SetValue(m_r, 5);
m_fiRowDrawFirst.SetValue(m_r, row);
m_fiRowDrawLast.SetValue(m_r, row);
m_miDrawCells.Invoke(m_r, new object[] { g });
brCellFore.Color=Color.Black;
brCell.Color=Color.White;
m_fiColDrawFirst.SetValue(m_r, 0);
m_fiColDrawLast.SetValue(m_r, 0);
m_fiRowDrawFirst.SetValue(m_r, 0);
m_fiRowDrawLast.SetValue(m_r, 0);
m_miDrawCells.Invoke(m_r, new object[] { g });
}
// You need to modify to meet your needs some kind of flag to turn on and
off color for a column
private bool CheckDealLevel(DataGrid dataGrid, int CurrentRow)
{
/*
if(dataGrid[CurrentRow,5].ToString().Equals("0"))
return false;
else
{
SqlCeDataReader myReader;
int numRows = ((DataTable)dataGrid.DataSource).Rows.Count;
myData.OpenDb();
DBAccess.CMD.CommandText="Select CaseAmt From Discount Where
Discount.Product="+dataGrid[CurrentRow, 16].ToString()+" Order By CaseAmt";
myReader = DBAccess.CMD.ExecuteReader();
int loop=1;
while(myReader.Read())
{
if(int.Parse(dataGrid[CurrentRow,3].ToString())==loop) //&&
myReader.GetDecimal(0)+decimal.Parse(dataGrid[CurrentRow,
25].ToString())==decimal.Parse(dataGrid[CurrentRow,24].ToString()))
if(myReader.GetFloat(0)+float.Parse(dataGrid[CurrentRow,
10].ToString())== float.Parse(dataGrid[CurrentRow, 9].ToString()))
return false;
loop=loop+1;
}
//myReader.Close();
myData.closeDb();
myReader.Dispose();
return true;
}
*/
return false;
}
}
}
Dont say it cant be done unless you have tried it yourself, and even if you
fail don't limit others around you!