diff --git a/README.md b/README.md
index be0ee7b..66844f1 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,423 @@
-# How to create custom column in winforms datagrid?
-This repositories contains the samples to create custom column in winforms datagrid
+# How to Create Custom Column in WinForms DataGrid?
+
+This repositories contains the samples to create custom column in [WinForms DataGrid](https://www.syncfusion.com/winforms-ui-controls/datagrid) (SfDataGrid).
+
+You can create a new column by deriving [GridColumn](https://help.syncfusion.com/cr/windowsforms/Syncfusion.WinForms.DataGrid.GridColumn.html) and create new a cell renderer by overriding the predefined renderer in DataGrid. The following steps describe how to create a sparkline column as a custom column.
+
+### Creating custom column
+
+You can create a custom column by overriding a new class from the **GridColumn** class.
+
+#### C#
+``` csharp
+public class GridSparklineColumn : GridColumn
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GridSparklineColumn()
+ {
+ SetCellType("Sparkline");
+ this.SparklineType = SparkLineType.Line;
+ }
+
+ ///
+ /// Gets or sets the type of the sparkline control.
+ ///
+ public SparkLineType SparklineType { get; set; }
+}
+```
+#### VB
+``` vb
+Public Class GridSparklineColumn
+ Inherits GridColumn
+ '''
+ ''' Initializes a new instance of the class.
+ '''
+ Public Sub New()
+ SetCellType("Sparkline")
+ Me.SparklineType = SparkLineType.Line
+ End Sub
+
+ '''
+ ''' Gets or sets the type of the sparkline control.
+ '''
+ Public Property SparklineType() As SparkLineType
+End Class
+```
+
+### Creating renderer
+
+After creating a custom column, you need to create renderer for the custom column. You can create custom renderer by deriving the [GridCellRendererBase](https://help.syncfusion.com/cr/windowsforms/Syncfusion.Windows.Forms.Grid.GridCellRendererBase.html) class.
+
+#### C#
+``` csharp
+///
+/// Represents a class that used for drawing the spark line cell.
+///
+public class GridSparklineCellRenderer : GridCellRendererBase
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The sparkline.
+ /// The DataGrid.
+ public GridSparklineCellRenderer(Syncfusion.Windows.Forms.Chart.SparkLine sparkline, SfDataGrid dataGrid)
+ {
+ Sparkline = sparkline;
+ DataGrid = dataGrid;
+ IsEditable = false;
+ }
+
+ ///
+ /// Gets or sets to specify the datagrid.
+ ///
+ protected SfDataGrid DataGrid { get; set; }
+
+ ///
+ /// Gets the sparkline control used to draw the sparkline.
+ ///
+ protected SparkLine Sparkline { get; set; }
+
+ ///
+ ///Renders the line type sparkline.
+ ///
+ /// The instance containing the event data.
+ /// The Sparkline.
+ public void DrawSparkline(Graphics graphics, Syncfusion.Windows.Forms.Chart.SparkLine sparkline)
+ {
+ SparkLineSource sparkLineSource = new SparkLineSource();
+ int areaMarginX = 3;
+ int areaMarginY = 3;
+ double firstPointX = 0, firstPointY = 0, secondPointX = 0, secondPointY = 0;
+ double areaWidth = sparkline.ControlWidth - areaMarginX * areaMarginX;
+ double areaHeight = sparkline.ControlHeight - areaMarginY * areaMarginY;
+
+ var sourceList = (List)sparkLineSource.GetSourceList(sparkline.Source, sparkline);
+
+ if (sourceList.Count == 0)
+ return;
+
+ double lineInterval = areaWidth / (sourceList.Count);
+ double lineRange = sparkline.HighPoint - sparkline.LowPoint;
+
+ for (int i = 0; i < sourceList.Count; i++)
+ {
+ double Value = Convert.ToDouble(sourceList[i]) - sparkline.LowPoint;
+
+ secondPointX = firstPointX;
+ secondPointY = firstPointY;
+
+ firstPointX = this.Sparkline.Location.X + (lineInterval * i + (lineInterval / 2));
+ firstPointY = this.Sparkline.Location.Y + (areaHeight - (areaHeight * (Value / lineRange)));
+
+ if (i > 0)
+ graphics.DrawLine(new Pen(sparkline.LineStyle.LineColor, 1), (float)(areaMarginX + firstPointX), (float)(areaMarginY + firstPointY), (float)(areaMarginX + secondPointX), (float)(areaMarginY + secondPointY));
+
+ if (sparkline.Markers.ShowMarker)
+ graphics.FillEllipse(new SolidBrush(sparkline.Markers.MarkerColor.BackColor), (float)(areaMarginX + firstPointX - 2), (float)(areaMarginY + firstPointY - 2), 5, 5);
+ if (Convert.ToDouble(sourceList[i]) == sparkline.StartPoint && sparkline.Markers.ShowStartPoint)
+ graphics.FillEllipse(new SolidBrush(sparkline.Markers.StartPointColor.BackColor), (float)(areaMarginX + firstPointX - 2), (float)(areaMarginY + firstPointY - 2), 5, 5);
+ if (Convert.ToDouble(sourceList[i]) == sparkline.EndPoint && sparkline.Markers.ShowEndPoint)
+ graphics.FillEllipse(new SolidBrush(sparkline.Markers.EndPointColor.BackColor), (float)(areaMarginX + firstPointX - 2), (float)(areaMarginY + firstPointY - 2), 5, 5);
+
+ if (sparkline.GetNegativePoint() != null)
+ {
+ int count = sparkline.GetNegativePoint().GetUpperBound(0);
+ for (int k = 0; k <= count; k++)
+ {
+ if (Convert.ToDouble(sourceList[i]) == (double)sparkline.GetNegativePoint().GetValue(k) && sparkline.Markers.ShowNegativePoint)
+ graphics.FillEllipse(new SolidBrush(sparkline.Markers.NegativePointColor.BackColor), (float)(areaMarginX + firstPointX - 2), (float)(areaMarginY + firstPointY - 2), 5, 5);
+ }
+ }
+
+ if (Convert.ToDouble(sourceList[i]) == sparkline.HighPoint && sparkline.Markers.ShowHighPoint)
+ graphics.FillEllipse(new SolidBrush(sparkline.Markers.HighPointColor.BackColor), (float)(areaMarginX + firstPointX - 2), (float)(areaMarginY + firstPointY - 2), 5, 5);
+ if (Convert.ToDouble(sourceList[i]) == sparkline.LowPoint && sparkline.Markers.ShowLowPoint)
+ graphics.FillEllipse(new SolidBrush(sparkline.Markers.LowPointColor.BackColor), (float)(areaMarginX + firstPointX - 2), (float)(areaMarginY + firstPointY - 2), 5, 5);
+ }
+ }
+
+ ///
+ /// Override to draw the spark line of the cell.
+ ///
+ /// The that used to draw the spark line.
+ /// The cell rectangle.
+ /// The cell value.
+ /// The CellStyleInfo of the cell.
+ /// The DataColumnBase of the cell.
+ /// The row and column index of the cell.
+ protected override void OnRender(Graphics graphics, Rectangle cellRect, string cellValue, CellStyleInfo style, DataColumnBase column, RowColumnIndex rowColumnIndex)
+ {
+ using (SolidBrush brush = new SolidBrush(style.BackColor))
+ graphics.FillRectangle(brush, cellRect);
+
+ var sparklineColumn = column.GridColumn as GridSparklineColumn;
+ this.Sparkline = new Syncfusion.Windows.Forms.Chart.SparkLine();
+ var record = this.DataGrid.GetRecordAtRowIndex(rowColumnIndex.RowIndex);
+
+ this.Sparkline.Source = GetSparklineSource(column.GridColumn.MappingName, record);
+ this.Sparkline.Type = sparklineColumn.SparklineType;
+ this.Sparkline.Markers.ShowEndPoint = true;
+ this.Sparkline.Markers.ShowHighPoint = true;
+ this.Sparkline.Markers.ShowLowPoint = true;
+ this.Sparkline.Markers.ShowMarker = true;
+ this.Sparkline.Markers.ShowNegativePoint = true;
+ this.Sparkline.Markers.ShowStartPoint = true;
+ this.Sparkline.Size = cellRect.Size;
+ this.Sparkline.Location = cellRect.Location;
+
+ var smoothingMode = graphics.SmoothingMode;
+ var clipBounds = graphics.VisibleClipBounds;
+ graphics.SetClip(cellRect);
+ graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
+ if (this.Sparkline.Type == SparkLineType.Line)
+ DrawSparkline(graphics, Sparkline);
+ else if (this.Sparkline.Type == SparkLineType.Column)
+ DrawSparkColumn(graphics, Sparkline);
+ else
+ DrawSparkWinLossColumn(graphics, Sparkline);
+
+ graphics.SmoothingMode = smoothingMode;
+ graphics.SetClip(clipBounds);
+ }
+
+ ///
+ /// Occurs when a key is pressed while the cell has focus.
+ ///
+ /// The DataColumnBase of the cell.
+ /// The row and column index of the cell.
+ /// The that contains the event data.
+ protected override void OnKeyDown(DataColumnBase dataColumn, RowColumnIndex rowColumnIndex, KeyEventArgs e)
+ {
+ var selectionController = this.DataGrid.SelectionController as CustomSelectionController;
+ switch (e.KeyCode)
+ {
+ case Keys.Space:
+ case Keys.Down:
+ case Keys.Up:
+ case Keys.Left:
+ case Keys.Right:
+ case Keys.Enter:
+ case Keys.PageDown:
+ case Keys.PageUp:
+ case Keys.Tab:
+ case Keys.Home:
+ case Keys.End:
+ selectionController.HandleKeyOperations(e);
+ break;
+ }
+
+ base.OnKeyDown(dataColumn, rowColumnIndex, e);
+ }
+
+ ///
+ /// Gets data to the sparkline column.
+ ///
+ /// The mapping name of the column.
+ /// Data of the SparkLine.
+ /// returns collection.
+ private double[] GetSparklineSource(string mappingName, object record)
+ {
+ var salesCollection = record as System.Data.DataRowView;
+ var item = salesCollection.Row.ItemArray[5];
+ return item as double[];
+ }
+}
+```
+#### VB
+``` vb
+'''
+''' Represents a class used for drawing the sparkline cell.
+'''
+Public Class GridSparklineCellRenderer
+ Inherits GridCellRendererBase
+ '''
+ ''' Initializes a new instance of the class.
+ '''
+ ''' The sparkline.
+ ''' The DataGrid.
+ Public Sub New(ByVal sparkline As Syncfusion.Windows.Forms.Chart.SparkLine, ByVal dataGrid As SfDataGrid)
+ Me.Sparkline = sparkline
+ Me.DataGrid = dataGrid
+ IsEditable = False
+ End Sub
+
+ '''
+ ''' Gets or sets to specify the datagrid.
+ '''
+ Protected Property DataGrid() As SfDataGrid
+
+ '''
+ ''' Gets the sparkline control used to draw the sparkline.
+ '''
+ Protected Property Sparkline() As SparkLine
+
+ '''
+ '''Renders the line type sparkline.
+ '''
+ ''' The instance containing the event data.
+ ''' The Sparkline.
+ Public Sub DrawSparkline(ByVal graphics As Graphics, ByVal sparkline As Syncfusion.Windows.Forms.Chart.SparkLine)
+ Dim sparkLineSource As New SparkLineSource()
+ Dim areaMarginX As Integer = 3
+ Dim areaMarginY As Integer = 3
+ Dim firstPointX As Double = 0, firstPointY As Double = 0, secondPointX As Double = 0, secondPointY As Double = 0
+ Dim areaWidth As Double = sparkline.ControlWidth - areaMarginX * areaMarginX
+ Dim areaHeight As Double = sparkline.ControlHeight - areaMarginY * areaMarginY
+
+ Dim sourceList = CType(sparkLineSource.GetSourceList(sparkline.Source, sparkline), List(Of Object))
+
+ If sourceList.Count = 0 Then
+ Return
+ End If
+
+ Dim lineInterval As Double = areaWidth / (sourceList.Count)
+ Dim lineRange As Double = sparkline.HighPoint - sparkline.LowPoint
+
+ For i As Integer = 0 To sourceList.Count - 1
+ Dim Value As Double = Convert.ToDouble(sourceList(i)) - sparkline.LowPoint
+
+ secondPointX = firstPointX
+ secondPointY = firstPointY
+
+ firstPointX = Me.Sparkline.Location.X + (lineInterval * i + (lineInterval / 2))
+ firstPointY = Me.Sparkline.Location.Y + (areaHeight - (areaHeight * (Value / lineRange)))
+
+ If i > 0 Then
+ graphics.DrawLine(New Pen(sparkline.LineStyle.LineColor, 1), CSng(areaMarginX + firstPointX), CSng(areaMarginY + firstPointY), CSng(areaMarginX + secondPointX), CSng(areaMarginY + secondPointY))
+ End If
+
+ If sparkline.Markers.ShowMarker Then
+ graphics.FillEllipse(New SolidBrush(sparkline.Markers.MarkerColor.BackColor), CSng(areaMarginX + firstPointX - 2), CSng(areaMarginY + firstPointY - 2), 5, 5)
+ End If
+ If Convert.ToDouble(sourceList(i)) = sparkline.StartPoint AndAlso sparkline.Markers.ShowStartPoint Then
+ graphics.FillEllipse(New SolidBrush(sparkline.Markers.StartPointColor.BackColor), CSng(areaMarginX + firstPointX - 2), CSng(areaMarginY + firstPointY - 2), 5, 5)
+ End If
+ If Convert.ToDouble(sourceList(i)) = sparkline.EndPoint AndAlso sparkline.Markers.ShowEndPoint Then
+ graphics.FillEllipse(New SolidBrush(sparkline.Markers.EndPointColor.BackColor), CSng(areaMarginX + firstPointX - 2), CSng(areaMarginY + firstPointY - 2), 5, 5)
+ End If
+
+ If sparkline.GetNegativePoint() IsNot Nothing Then
+ Dim count As Integer = sparkline.GetNegativePoint().GetUpperBound(0)
+ For k As Integer = 0 To count
+ If Convert.ToDouble(sourceList(i)) = CDbl(sparkline.GetNegativePoint().GetValue(k)) AndAlso sparkline.Markers.ShowNegativePoint Then
+ graphics.FillEllipse(New SolidBrush(sparkline.Markers.NegativePointColor.BackColor), CSng(areaMarginX + firstPointX - 2), CSng(areaMarginY + firstPointY - 2), 5, 5)
+ End If
+ Next k
+ End If
+
+ If Convert.ToDouble(sourceList(i)) = sparkline.HighPoint AndAlso sparkline.Markers.ShowHighPoint Then
+ graphics.FillEllipse(New SolidBrush(sparkline.Markers.HighPointColor.BackColor), CSng(areaMarginX + firstPointX - 2), CSng(areaMarginY + firstPointY - 2), 5, 5)
+ End If
+ If Convert.ToDouble(sourceList(i)) = sparkline.LowPoint AndAlso sparkline.Markers.ShowLowPoint Then
+ graphics.FillEllipse(New SolidBrush(sparkline.Markers.LowPointColor.BackColor), CSng(areaMarginX + firstPointX - 2), CSng(areaMarginY + firstPointY - 2), 5, 5)
+ End If
+ Next i
+ End Sub
+
+ '''
+ ''' Overrides to draw the sparkline of the cell.
+ '''
+ ''' The that used to draw the spark line.
+ ''' The cell rectangle.
+ ''' The cell value.
+ ''' The CellStyleInfo of the cell.
+ ''' The DataColumnBase of the cell.
+ ''' The row and column index of the cell.
+ Protected Overrides Sub OnRender(ByVal graphics As Graphics, ByVal cellRect As Rectangle, ByVal cellValue As String, ByVal style As CellStyleInfo, ByVal column As DataColumnBase, ByVal rowColumnIndex As RowColumnIndex)
+ Using brush As New SolidBrush(style.BackColor)
+ graphics.FillRectangle(brush, cellRect)
+ End Using
+
+ Dim sparklineColumn = TryCast(column.GridColumn, GridSparklineColumn)
+ Me.Sparkline = New Syncfusion.Windows.Forms.Chart.SparkLine()
+ Dim record = Me.DataGrid.GetRecordAtRowIndex(rowColumnIndex.RowIndex)
+
+ Me.Sparkline.Source = GetSparklineSource(column.GridColumn.MappingName, record)
+ Me.Sparkline.Type = sparklineColumn.SparklineType
+ Me.Sparkline.Markers.ShowEndPoint = True
+ Me.Sparkline.Markers.ShowHighPoint = True
+ Me.Sparkline.Markers.ShowLowPoint = True
+ Me.Sparkline.Markers.ShowMarker = True
+ Me.Sparkline.Markers.ShowNegativePoint = True
+ Me.Sparkline.Markers.ShowStartPoint = True
+ Me.Sparkline.Size = cellRect.Size
+ Me.Sparkline.Location = cellRect.Location
+
+ Dim smoothingMode = graphics.SmoothingMode
+ Dim clipBounds = graphics.VisibleClipBounds
+ graphics.SetClip(cellRect)
+ graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality
+ If Me.Sparkline.Type = SparkLineType.Line Then
+ DrawSparkline(graphics, Sparkline)
+ ElseIf Me.Sparkline.Type = SparkLineType.Column Then
+ DrawSparkColumn(graphics, Sparkline)
+ Else
+ DrawSparkWinLossColumn(graphics, Sparkline)
+ End If
+
+ graphics.SmoothingMode = smoothingMode
+ graphics.SetClip(clipBounds)
+ End Sub
+
+ '''
+ ''' Occurs when the key is pressed while the cell has focus.
+ '''
+ ''' The DataColumnBase of the cell.
+ ''' The row and column index of the cell.
+ ''' The that contains the event data.
+ Protected Overrides Sub OnKeyDown(ByVal dataColumn As DataColumnBase, ByVal rowColumnIndex As RowColumnIndex, ByVal e As KeyEventArgs)
+ Dim selectionController = TryCast(Me.DataGrid.SelectionController, CustomSelectionController)
+ Select Case e.KeyCode
+ Case Keys.Space, Keys.Down, Keys.Up, Keys.Left, Keys.Right, Keys.Enter, Keys.PageDown, Keys.PageUp, Keys.Tab, Keys.Home, Keys.End
+ selectionController.HandleKeyOperations(e)
+ End Select
+
+ MyBase.OnKeyDown(dataColumn, rowColumnIndex, e)
+ End Sub
+
+ '''
+ ''' Gets data to the sparkline column.
+ '''
+ ''' The mapping name of the column.
+ ''' Data of the SparkLine.
+ ''' returns collection.
+ Private Function GetSparklineSource(ByVal mappingName As String, ByVal record As Object) As Double()
+ Dim salesCollection = TryCast(record, System.Data.DataRowView)
+ Dim item = salesCollection.Row.ItemArray(5)
+ Return TryCast(item, Double())
+ End Function
+```
+
+### Adding the custom renderer to CellRenderers collection
+
+By using the following code, you can add the previous created custom renderer to the [SfDataGrid.CellRenderers](https://help.syncfusion.com/cr/windowsforms/Syncfusion.Windows.Forms.Grid.GridCellRendererCollection.html) collection.
+
+#### C#
+``` csharp
+this.sfDataGrid1.CellRenderers.Add("Sparkline", new GridSparklineCellRenderer(new Syncfusion.Windows.Forms.Chart.SparkLine(), this.sfDataGrid1));
+```
+
+#### VB
+``` vb
+Me.sfDataGrid1.CellRenderers.Add("Sparkline", New GridSparklineCellRenderer(New Syncfusion.Windows.Forms.Chart.SparkLine(), Me.sfDataGrid1))
+```
+
+### Loading custom column
+
+By using the following code, you can define the custom column in DataGrid.
+
+#### C#
+``` csharp
+this.sfDataGrid1.Columns.Add(new GridSparklineColumn() { MappingName = "Sparkline", HeaderText = "Analysis Report", Width = 150, AllowFiltering = false });
+```
+
+#### VB
+``` vb
+Me.sfDataGrid1.Columns.Add(New GridSparklineColumn() With {.MappingName = "Sparkline", .HeaderText = "Analysis Report", .Width = 150, .AllowFiltering = False})
+```
+
+
+
+Here, a rating column has been created as a custom column. A sample for this is available in this repository.
diff --git a/SparklineColumn.png b/SparklineColumn.png
new file mode 100644
index 0000000..ed6472a
Binary files /dev/null and b/SparklineColumn.png differ