Professional UI Solutions
Site Map   /  Register
 
 
 

Styles and Formatting

Introduction

This article details on styles and style inheritance implemented in the Elegant Grid. Using simple inheritance rules, you can easily and flexibly customize the way your grid looks and feels like. The built-in inheritance mechanism allows you to set styles for a cell of any supported type at the levels of the whole grid, column, row and cell. All this requires little effort from your side and results in very low processor overhead at run time.

Styles and Style Inheritance

Each cell has a Cell.Style property that specifies the appearance of a cell (for example, the background color, text font, text color, content padding, and etc.). Each cell type features its own cell style that is inherited from the CellStyle class. For example, the TextCell cell class uses the TextCellStyle class and NumericCell uses NumericCellStyle. As you can see, the name of a style class is composed by adding the Style suffix to the name of its cell type.

There is a good chance that you may need to define the same style for the whole grid, for a particular column/row, or for some group of cells. The Elegant Grid supports a five-level inheritance hierarchy for styles (See Figure 1).

Style inheritance in the Elegant Grid

Figure 1 Style inheritance in the Elegant Grid

The general rule for styles at different levels is that a style at a higher level takes precedence over a style defined at the lower level. For instance, if the background color at the row level is set to red and at the grid level is set to blue, the row will have the red background.

The three lowest levels are collections of the CellStyleCollection type. Each collection can store objects of all supported cell styles. By default, the collection at each level is empty but when you customize some cell type at a particular level, the correspondent cell style is added to the collection. For example, you can specify the TextCellStyle.TextColor property value for the grid to make each text cell use this value:

[C#]
TextCellStyle textStyle = 
(TextCellStyle)unboundGridControl1.CellStyles[typeof(TextCellStyle)];
textStyle.TextColor = Color.Red;

[VB.NET]
Dim textStyle As TextCellStyle = _ 
UnboundGridControl1.CellStyles(GetType(TextCellStyle))
textStyle.TextColor = Color.Red

The Cell.Style level is designed to allow you to customize the appearance of a particular cell.

Please notice that, if a style property value is specified on a higher level, it doesn’t inherit the corresponding value from a lower level. For instance, if you set the CellStyle.BackgroundColor property value for a specified column, it will override the grid value for this property.

NOTE: The DataRow.CellStyles property is only available for the unbound grid. It is always null for the bound grid.

The top level specifies how a cell finally looks as a result of applying styles from lower levels according to the general rule of style inheritance. You can use a Cell.GetInheritedStyleClone method to get a copy of this final style object, which is directly used for layout and rendering. Here is a code snippet that shows how styles are applied at different levels:

[C#]
UnboundGridControl unboundGridControl1 = new UnboundGridControl();
unboundGridControl1.AutoCreateCells = true;

Column nameColumn = new Column();
nameColumn.HeaderText = "Name";
nameColumn. DataPropertyName = "Name";
         
unboundGridControl1.Columns.AddRange(
new Column[]
   {
      // ...
      nameColumn
      // ...
   });

// The following code sets the background color for all the cells 
// in the grid to red

unboundGridControl1.CellStyles[typeof(CellStyle)].BackgroundColor =
   Color.Red;

// The code below sets the background color for the cells in the nameColumn
// to green, this overrides the background color that was set for the
// grid
nameColumn.CellStyles[typeof(CellStyle)].BackgroundColor = Color.Green;

// The following code adds row to the grid and specifies blue color for the
// cell within row
DataRow row = unboundGridControl1.NewDataRow();
row.CellStyles[typeof(CellStyle)].BackgroundColor = Color.Blue;

// In here, the background color for a certain cell is specified.
// This value overrides all the previous ones
row.Cells[nameColumn].Style.BackgroundColor = Color.Yellow;

[VB.NET]
Dim unboundGridControl1 = New UnboundGridControl
unboundGridControl1.AutoCreateCells = True

Dim nameColumn = New Column
nameColumn.HeaderText = "Name"
nameColumn. DataPropertyName = "Name"

unboundGridControl1.Columns.AddRange( New Column() { nameColumn } )

' The following code sets the background color for all the cells in the grid
' to red
unboundGridControl1.CellStyles(GetType(CellStyle)).BackgroundColor = _ 
   Color.Red

' The code below sets the background color for the cells in the nameColumn to
' green, this overrides the background color that was set for the grid
nameColumn.CellStyles(GetType(CellStyle)).BackgroundColor = Color.Green

' The following code adds row to the grid and specifies blue color for the
' cell within row
Dim row = unboundGridControl1.NewDataRow()
row.CellStyles(GetType(CellStyle)).BackgroundColor = Color.Blue

' In here, the background color for a certain cell is specified.
' This value overrides all the previous ones
row.Cells(nameColumn).Style.BackgroundColor = Color.Yellow

Style Events

There are two events designed to make the work with cell styles more flexible.

The GridControlBase.CellStyleCreated event occurs when a cell is created and its style is initialized. At this point, you can specify style properties which override the default and inherited values. The method that handles this event takes an argument of the CellStyleEventArgs type. The CellStyleEventArgs.Style property allows you to modify the cell style.

The following sample shows how to initially mark each cell with an expired date:

[C#]
using Elegant.Grid;

private void boundGridControl1_CellStyleCreated(
   object sender, CellStyleEventArgs e)
{
   if(e.Cell.Column != ExpirationDateColumn)
      return;

   DateTimeCell cell = (DateTimeCell)e.Cell;
   if((DateTime)cell.DisplayValue > DateTime.Now)
      e.Style.BackgroundColor = Color.Red;
}

[VB.NET]
Imports Elegant.Grid

Private Sub BoundGridControl1_CellStyleCreated( _
ByVal sender As System.Object, ByVal e As _ 
Elegant.Grid.CellStyleEventArgs) Handles BoundGridControl1.ModifyCellStyle
   If (Not e.Cell.Column Is ExpirationDateColumn) Then
      Return
   End If

   Dim cell As DateTimeCell = e.Cell
   If (DirectCast(cell.DisplayValue, DateTime) > DateTime.Now) Then
      e.Style.BackgroundColor = Color.Red
   End If
End Sub

The second event is GridControlBase.ModifyCellStyle, which is raised every time when a cell is about to update its layout or to paint its content. At this point, the final cell style (the top level of the inheritance hierarchy) has been calculated and you can additionally customize it. The event handler receives an argument of type ModifyCellStyleEventArgs derived from CellStyleEventArgs. This ModifyCellStyleEventArgs object additionally features the ModifyCellStyleEventArgs.PerformLayout property that indicates whether the layout should be updated to reflect any change in the style that affect the grid layout. Since updating the layout requires additional processor time, do not set ModifyCellStyleEventArgs.PerformLayout to true unless you actually need to update the layout (for example, you redefine a style in such a way that the layout needs to be updated on the cell).

Because the GridControlBase.CellStyleCreated event occurs only when the cell is created and GridControlBase.ModifyCellStyle is raised each time when the cell is about to paint its content or update its layout, the former is preferable if you do not need to change cell styles according to one or more conditions (for example, in the Elegant Media Player sample, the currently playing file is drawn in white and all other files in green).

The following example illustrates how the GridControlBase.ModifyCellStyle event can be used for highlighting a row in the play list to indicate that the current track is played:

[C#]
using Elegant.Grid;

private void Form1_Load(object sender, System.EventArgs e)
{
   Column trackName = new Column();
   trackName.HeaderText = "Name";
   trackName.DataPropertyName = "Name";

   Column playTime = new Column();
   playTime.HeaderText = "Time";
   playTime.DataPropertyName = "PlayTime";
   DateTimeCellStyle dateTimeCellStyle = 
      (DateTimeCellStyle)ModifiedDateColumn.
      CellStyles[typeof(DateTimeCellStyle)];
   dateTimeCellStyle.Format = DateTimePickerFormat.Custom;
   dateTimeCellStyle.CustomFormat = "t";

   boundGridControl1.Columns.AddRange(new Column[]{trackName, playTime});

   // Additional initalization goes here
}

private void boundGridControl1_ModifyCellStyle(object sender,
   Elegant.Grid.ModifyCellStyleEventArgs e)
{
   TextCellStyle style = (TextCellStyle)e.Style;
   if(e.Cell.Row.Index == currentlyPlayedTrackIndex)
      style.TextColor = Color.White;
}

[VB.NET]
Imports Elegant.Grid

Private Sub Form1_Load(ByVal sender As System.Object, _ 
ByVal e As System.EventArgs) Handles MyBase.Load
   dataAdapter.Fill(dataSet)
        
   Dim trackName = New Column
   trackName.HeaderText = "Name"
   trackName.DataPropertyName = "Name"

   Dim playTime = New Column
   playTime.HeaderText = "Time"
   playTime.DataPropertyName = "PlayTime"
   Dim dateTimeCellStyle = _
      ModifiedDateColumn.CellStyles(GetType(DateTimeCellStyle))
   dateTimeCellStyle.Format = DateTimePickerFormat.Custom
   dateTimeCellStyle.CustomFormat = "t"

   BoundGridControl1.Columns.AddRange(New Column() {trackName, playTime})

   ' Additional initialization here…
End Sub

Private Sub BoundGridControl1_ModifyCellStyle(ByVal sender As _
System.Object, ByVal e As Elegant.Grid.ModifyCellStyleEventArgs _
) Handles BoundGridControl1.ModifyCellStyle
   Dim style As TextCellStyle = e.Style
   If (e.Cell.Row.Index = currentlyPlayedTrackIndex) Then
      style.TextColor = Color.White
   End If
End Sub

The following example illustrates the style inheritance mechanism.

[C#]
using Elegant.Grid;

private void Form1_Load(object sender, System.EventArgs e)
{
   dataAdapter.Fill(dataSet);
   //
   // Initialization code goes here...
   //

   // Specify the background color and the hovered background color
   // for the whole grid
   CellStyle style1 = boundGridControl1.CellStyles[typeof(CellStyle)];
   style1.BackgroundColor = Color.Honeydew;
   style1.HoveredBackgroundColor = Color.Cyan;

   // Override the grid background color settings for the
   // CreditCardIDColumn column
   CellStyle style2 =  CreditCardIDColumn.CellStyles[typeof(CellStyle)];
   style2.BackgroundColor = Color.LightBlue;

   // Align center the content of the cells in ModifiedDateColumn
   DateTimeCellStyle dateTimeStyle = (DateTimeCellStyle)
      ModifiedDateColumn.CellStyles[typeof(DateTimeCellStyle)];
   dateTimeStyle.TextAlignment = ContentAlignment.MiddleCenter;
}

private void boundGridControl1_ModifyCellStyle(object sender,
   Elegant.Grid.ModifyCellStyleEventArgs e)
{
   if(e.Cell is ColumnHeaderCell || e.Cell is GroupRowCell ||
      e.Cell.Column == CreditCardIDColumn)
      return;

   // Set the background color of cell to Color.LightPink if
   // the credit card is expired
   DataRow dataRow = e.Cell.Row as DataRow;
   NumericCell expYearCell = (NumericCell)
      dataRow.Cells.FindByColumn(ExpYearColumn);
   NumericCell expMonthCell = (NumericCell)
      dataRow.Cells.FindByColumn(ExpMonthColumn);

   DateTime currentDate = DateTime.Now;
         
   try
   {
      decimal expYear = (decimal)expYearCell.DisplayValue, 
              expMonth = (decimal)expMonthCell.DisplayValue;
            
      if(expYear < currentDate.Year || 
         (expYear == currentDate.Year && expMonth < currentDate.Month) )
         {
            e.Cell.Style.BackgroundColor = Color.LightPink;
         }
   }
   catch(Exception)
   {
      //…
   }
}

[VB.NET]
Imports Elegant.Grid

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _ 
System.EventArgs) Handles MyBase.Load
   dataAdapter.Fill(DataSet)

   ' Specify the background color and the hovered background color 
   ' for the whole grid
   Dim style1 = BoundGridControl1.CellStyles(GetType(CellStyle))
   style1.BackgroundColor = Color.Honeydew
   style1.HoveredBackgroundColor = Color.Cyan

   ' Override the grid background color settings for the
   ' CreditCardIDColumn column.
   Dim style2 = CreditCardIDColumn.CellStyles(GetType(CellStyle))
   style2.BackgroundColor = Color.LightBlue

   ' Align center the content of the cells in ModifiedDateColumn.
   Dim dateTimeStyle as DateTimeCellStyle = _
      ModifiedDateColumn.CellStyles(GetType(DateTimeCellStyle))
   dateTimeStyle.TextAlignment = ContentAlignment.MiddleCenter
End Sub

Private Sub BoundGridControl1_ModifyCellStyle(ByVal sender As _
System.Object, _ ByVal e As Elegant.Grid.ModifyCellStyleEventArgs) Handles _
BoundGridControl1.ModifyCellStyle
   If (e.Cell.GetType Is GetType(ColumnHeaderCell) Or _
       e.Cell.GetType Is GetType(GroupRowCell) Or _
       e.Cell.Column Is CreditCardIDColumn) Then
      Return
   End If

   ' Set the background color of cell to Color.LightPink if
   ' the credit card is expired

   Dim dataRow As DataRow = e.Cell.Row
   Dim expYearCell As NumericCell = _ 
      dataRow.Cells.FindByColumn(ExpYearColumn)
   Dim expMonthCell As NumericCell = _ 
      dataRow.Cells.FindByColumn(ExpMonthColumn)

   Dim currentDate = DateTime.Now

   Try
      Dim expYear As Decimal = expYearCell.DisplayValue, _
         expMonth As Decimal = expMonthCell.DisplayValue

      If (expYear < currentDate.Year Or _
         (expYear = currentDate.Year And expMonth < currentDate.Month)) Then
         e.Cell.Style.BackgroundColor = Color.LightPink
      End If
      Catch ex As Exception
   End Try
End If
End Sub

The code above produces the grid shown on Figure 2.

Grid with customized appearance

Figure 2 Grid with customized appearance

Customizing Styles at the Row Level for the Bound Grid

The bound grid is designed in a way to minimize the memory overhead and improve the performance, which is especially important for working with large volumes of data. This is achieved by creating only those cells that are visible at any given moment. When you scroll the grid window, some cells are destroyed and new cells are created. This makes impossible to dynamically set cell styles for rows that are not currently created. To customize the appearance of cells at the row level, use the GridControlBase.ModifyCellStyle event. Here is a small example that shows how you may alternate the background color for odd and even rows (See Figure 3):

[C#]
using Elegant.Grid;

private void boundGridControl1_ModifyCellStyle(object sender,
   Elegant.Grid.ModifyCellStyleEventArgs e)
{
   if(e.Cell.Row.Index % 2 == 0)
      e.Style.BackgroundColor = Color.LightGray;
   else
      e.Style.BackgroundColor = Color.Honeydew;
}

[VB.NET]
Imports Elegant.Grid

Private Sub BoundGridControl1_ModifyCellStyle( ByVal sender As _
System.Object, ByVal e As Elegant.Grid.ModifyCellStyleEventArgs) Handles _ 
BoundGridControl1.ModifyCellStyle
   If (e.Cell.Row.Index Mod 2 = 0) Then
      e.Style.BackgroundColor = Color.LightGray
   Else
      e.Style.BackgroundColor = Color.Honeydew
   End If
End Sub

Alternate rows colored in green and gray

Figure 3 Alternate rows colored in green and gray

Customizing and Setting Styles at Design Time

You can tweak the supported cell styles with the Cell Styles Editor window in the Component Designer (click the ellipsis button next to the CellStyles property).

Cell Styles Editor window

Figure 4 Cell Styles Editor window

Another available option in the Component Designer is the Column Collection Editor (See Figure 5). You can invoke it by clicking the ellipsis button next to the Column property. The window allows you to set desired style types for particular columns.

Column Selection Editor window

Figure 5 Column Selection Editor window

Back To Top Other Articles...