Articles in this section
Category / Section

How to create multi-select dropdown grid in a cell of WinForms GridControl?

5 mins read

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.

C#

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

VB

'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 Class

Creating CellRenderer:

The behavior of the cell is defined in the custom cell renderer.

C#

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

VB

'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 Class

Overrides in DropDownGridCellRenderer class:

The custom cell renderer class needs to override the following methods to implement the Multi-Select DropDown cell.

C#

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

VB

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 Function

Adding CellModel:

The object is created for the DropDownGridCellModel and it is added to the GridControl.CellModel.

C#

//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);

VB

'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:

C#

//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());
}

VB

'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

 

Multi-select dropdown in grid control

Figure 1: Multi-Select DropDown in Grid Control

Selected items in the dropdown

Figure 2: Selected Items in the DropDown

Samples:

C#: MultiSelectDropDown

VB: MultiSelectDropDown

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please sign in to leave a comment
Access denied
Access denied