How to create multi-select dropdown in a cell of WinForms GridControl?
Multi-select dropdown grid
To create a
cell that has multi-selection dropdown grid, you have to use a derived custom
cell from the GridDropDownGridCellModel and the GridDropDownGridCellRenderer.
In the derived renderer, the code embeds the WinForms
Grid Control whose ListBoxSelectionMode is set to MultiSimple. The
renderer uses the DropDownContainerCloseDropDown override to move the text in
the selected rows of the embedded grid into a string that is set into the
style. The CellValue of the cell in the parent grid that hosts this custom cell
type lists the selected options as a hyphen delimited string for every column
and the New Line delimited string for every row.
Creating CellModel:
The custom
cell model is derived from the GridDropDownGridCellModel. The custom cell
renderer object is invoked by the CreateRenderer() method.
//Deriving the GridDropDownGridCellModel.
public class DropDownGridCellModel : GridDropDownGridCellModel
{
private GridControlBase _embbeddedGrid;
public GridControlBase EmbeddedGrid
{
get
{
if (_embbeddedGrid == null)
_embbeddedGrid = new GridControlBaseImp();
return _embbeddedGrid;
}
set
{
_embbeddedGrid = value;
}
}
protected DropDownGridCellModel(SerializationInfo info, StreamingContext context) : base(info, context) { }
public DropDownGridCellModel(GridModel grid) : base(grid) { }
public override GridCellRendererBase CreateRenderer(GridControlBase control)
{
return new DropDownGridCellRenderer(control, this);
}
}'Deriving the GridDropDownGridCellModel.
Public Class DropDownGridCellModel
Inherits GridDropDownGridCellModel
Private _embbeddedGrid As GridControlBase
Public Property EmbeddedGrid() As GridControlBase
Get
If _embbeddedGrid Is Nothing Then
_embbeddedGrid = New GridControlBaseImp()
End If
Return _embbeddedGrid
End Get
Set(ByVal value As GridControlBase)
_embbeddedGrid = value
End Set
End Property
Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
MyBase.New(info, context)
End Sub
Public Sub New(ByVal grid As GridModel)
MyBase.New(grid)
End Sub
Public Overrides Function CreateRenderer(ByVal control As GridControlBase) As GridCellRendererBase
Return New DropDownGridCellRenderer(control, Me)
End Function
End Class
'Override the CreateRenderer() in the Base class.
Public Overrides Function CreateRenderer(ByVal control As GridControlBase) As GridCellRendererBase
'Return the Custom Renderer Object.
Return New FolderBrowserCellRenderer(control, Me)
End Function
End ClassCreating CellRenderer:
The behavior
of the cell is defined in the custom cell renderer.
//Deriving the GridDropDownGridCellRenderer.
public class DropDownGridCellRenderer : GridDropDownGridCellRenderer
{
GridControl grid;
public DropDownGridCellRenderer(GridControlBase grid, GridCellModelBase cellModel) : base(grid, cellModel)
{
//Disable the TextBox in the base class renderer.
this.DisableTextBox = true;
//Add the DropDown Button as the ComboBox button.
DropDownButton = new GridCellComboBoxButton(this);
this.grid = null;
}
}'Deriving the GridDropDownGridCellRenderer.
Public Class DropDownGridCellRenderer
Inherits GridDropDownGridCellRenderer
Private grid As GridControl
Public Sub New(ByVal grid As GridControlBase, ByVal cellModel As GridCellModelBase)
MyBase.New(grid, cellModel)
'Disable the TextBox in the base class renderer.
Me.DisableTextBox = True
'Add the DropDown Button as the ComboBox button
DropDownButton = New GridCellComboBoxButton(Me)
Me.grid = Nothing
End Sub
End ClassOverrides in DropDownGridCellRenderer class:
The custom
cell renderer class needs to override the following methods to implement
the Multi-Select DropDown cell.
protected override void OnInitialize(int rowIndex, int colIndex)
{
this.grid = ((DropDownGridCellModel)this.Model).EmbeddedGrid as GridControl;
this.grid.Dock = DockStyle.Fill;
//Sets the Selection Type of the DropDownGrid.
this.grid.ListBoxSelectionMode = SelectionMode.MultiSimple;
base.OnInitialize(rowIndex, colIndex);
}
protected override void InitializeDropDownContainer()
{
base.InitializeDropDownContainer();
//this.DropDownContainer.FormBorderStyle = FormBorderStyle.SizableToolWindow;
this.DropDownContainer.IgnoreDialogKey = true;
}
//Changes the ControlValue if dropdown was closed with Done.
public override void DropDownContainerCloseDropDown(object sender, PopupClosedEventArgs e)
{
this.Grid.Model[this.RowIndex, this.ColIndex].Text = this.ParseString();
// To measure the Width and Height of the parsed string with corresponding font of the Grid.
Size s = this.grid.CreateGraphics().MeasureString(this.Grid.Model[this.RowIndex, this.ColIndex].Text, this.Grid.Model[this.RowIndex, this.ColIndex].Font.GdipFont).ToSize();
//Sets the Value of the Height and width to the Grid.
//this.Grid.Model.RowHeights[this.RowIndex] = s.Height + 10 ;
//this.Grid.Model.ColWidths[this.ColIndex] = s.Width + 20 ;
Grid.InvalidateRange(GridRangeInfo.Cell(RowIndex, ColIndex), GridRangeOptions.MergeCoveredCells); // Merge all cells
base.DropDownContainerCloseDropDown(sender, e);
}
//Used to parse the values in the Cells.
private string ParseString()
{
string str = "";
//Get the range for selected rows.
GridRangeInfoList gridList = this.grid.Selections.GetSelectedRows(true, true);
//Gets the Enumarator from RangeList
IEnumerator ie = gridList.GetEnumerator();
while (ie.MoveNext())
{
//To replace the string where R is found.
string paresedString = Regex.Replace(ie.Current.ToString(), "R", "");
//Matches the ':' for finding ranges.
if (Regex.Match(paresedString, ":").Success)
{
//Matches the digits in the Range.
Match m = Regex.Match(paresedString, @"\d+");
if (m.Success)
{
int rowBegin = int.Parse(m.Value);
int rowEnd = 0;
if (m.NextMatch().Success)
{
rowEnd = int.Parse(m.NextMatch().Value);
}
// fetches the values to the cells and store into the string called str.
// Column values are separator by hyphen '-'
// row values are separator by '\n';
for (int k = rowBegin; k <= rowEnd; k++)
{
for (int i = 0; i < this.grid.Model.ColCount; i++)
{
str += this.grid.Model[k, i].Text + "-";
}
str += "\n";
}
}
}
else
{
int row = int.Parse(paresedString);
//To parse the single row.
for (int i = 0; i < this.grid.Model.ColCount; i++)
{
str += this.grid.Model[row, i].Text + "-";
}
str += "\n";
}
}
return str;
}
//Create the DropDown Grid and its styles.
protected override Control CreateInnerControl(out GridControlBase grid)
{
grid = this.grid;
grid.Dock = DockStyle.Fill;
grid.CausesValidation = false;
return grid;
}Protected Overrides Sub OnInitialize(ByVal rowIndex As Integer, ByVal colIndex As Integer)
Me.grid = TryCast((CType(Me.Model, DropDownGridCellModel)).EmbeddedGrid, GridControl)
Me.grid.Dock = DockStyle.Fill
'Sets the Selection Type of the DropDownGrid.
Me.grid.ListBoxSelectionMode = SelectionMode.MultiSimple
MyBase.OnInitialize(rowIndex, colIndex)
End Sub
Protected Overrides Sub InitializeDropDownContainer()
MyBase.InitializeDropDownContainer()
'this.DropDownContainer.FormBorderStyle = FormBorderStyle.SizableToolWindow;
Me.DropDownContainer.IgnoreDialogKey = True
End Sub
'Used to change the ControlValue if dropdown was closed with Done.
Public Overrides Sub DropDownContainerCloseDropDown(ByVal sender As Object, ByVal e As PopupClosedEventArgs)
Me.Grid.Model(Me.RowIndex, Me.ColIndex).Text = Me.ParseString()
' To measure the Width and Height of the parsed string with corresponding font of the Grid.
Dim s As Size = Me.grid.CreateGraphics().MeasureString(Me.Grid.Model(Me.RowIndex, Me.ColIndex).Text, Me.Grid.Model(Me.RowIndex, Me.ColIndex).Font.GdipFont).ToSize()
'Sets the Value of the Height and width to the Grid.
'this.Grid.Model.RowHeights[this.RowIndex] = s.Height + 10 ;
'this.Grid.Model.ColWidths[this.ColIndex] = s.Width + 20 ;
Grid.InvalidateRange(GridRangeInfo.Cell(RowIndex, ColIndex), GridRangeOptions.MergeCoveredCells) ' Merge all cells
MyBase.DropDownContainerCloseDropDown(sender, e)
End Sub
'Used to parse the values in the Cells
Private Function ParseString() As String
Dim str As String = ""
'Get the range for selected rows.
Dim gridList As GridRangeInfoList = Me.grid.Selections.GetSelectedRows(True, True)
'Gets the Enumarator from RangeList.
Dim ie As IEnumerator = gridList.GetEnumerator()
Do While ie.MoveNext()
'To replace the string where R is found.
Dim paresedString As String = Regex.Replace(ie.Current.ToString(), "R", "")
'Matches the ':' for finding ranges.
If Regex.Match(paresedString, ":").Success Then
'Matches the digits in the Range.
Dim m As Match = Regex.Match(paresedString, "\d+")
If m.Success Then
Dim rowBegin As Integer = Integer.Parse(m.Value)
Dim rowEnd As Integer = 0
If m.NextMatch().Success Then
rowEnd = Integer.Parse(m.NextMatch().Value)
End If
'Fetches the values to the cells and store into the string called str.
'Column values are separator by hyphen '-'
'Row values are separator by '\n';
For k As Integer = rowBegin To rowEnd
For i As Integer = 0 To Me.grid.Model.ColCount - 1
str &= Me.grid.Model(k, i).Text & "-"
Next i
str &= Constants.vbLf
Next k
End If
Else
Dim row As Integer = Integer.Parse(paresedString)
'To parse the single row.
For i As Integer = 0 To Me.grid.Model.ColCount – 1
str &= Me.grid.Model(row, i).Text & "-"
Next i
str &= Constants.vbLf
End If
Loop
Return str
End Function
'Create the DropDown Grid and it's styles.
Protected Overrides Function CreateInnerControl(<System.Runtime.InteropServices.Out()> ByRef grid As GridControlBase) As Control
grid = Me.grid
grid.Dock = DockStyle.Fill
grid.CausesValidation = False
Return grid
End FunctionAdding CellModel:
The object is
created for the DropDownGridCellModel and it is added to
the GridControl.CellModel.
//Creates the instance of the DropdownGrid Model.
DropDownGridCellModel dropDownModel = new DropDownGridCellModel(this.gridControl1.Model);
dropDownModel.EmbeddedGrid = GridA;
//To register the DropDownGridCellModel to the GridModel.
gridControl1.CellModels.Add("MultiSelectDropDown", dropDownModel);'Creates the instance of the DropdownGrid Model.
Dim dropDownModel As New DropDownGridCellModel(Me.gridControl1.Model)
dropDownModel.EmbeddedGrid = GridA
'To register the DropDownGridCellModel to the GridModel.
gridControl1.CellModels.Add("MultiSelectDropDown", dropDownModel)Assigning CellType:
//Set the cell type to the FolderBrowser.
this.gridControl1[2, 3].CellType = "MultiSelectDropDown";
private void button1_Click(object sender, EventArgs e)
{
//Writes the Selected Items in The DropDownGrid to the Output.
Console.WriteLine(this.gridControl1[2, 3].CellValue.ToString());
}'Set the cell type to the FolderBrowser.
Private Me.gridControl1(2, 3).CellType = "MultiSelectDropDown"
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs)
'Writes the Selected Items in The DropDownGrid to the Output.
Console.WriteLine(Me.gridControl1(2, 3).CellValue.ToString())
End Sub

Figure 1: Multi-Select DropDown in Grid Control

Figure 2: Selected Items in the DropDown
Samples:
Conclusion
I hope you enjoyed learning about how to create multi-select dropdown in a cell of WinForms Grid.
You can refer to our WinForms GridControl feature tour page to know about its other groundbreaking feature representations and WinForms GridControl documentation, and how to quickly get started for configuration specifications. You can also explore our WinForms GridControl example to understand how to create and manipulate data.
For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion, you can try our 30-day free trial to check out our other controls.
If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, Direct-Trac, or feedback portal. We are always happy to assist you!