This is a migrated thread and some comments may be shown as answers.

column not showing data when switching out the cell element to a custom type

4 Answers 103 Views
GridView
This is a migrated thread and some comments may be shown as answers.
dd
Top achievements
Rank 1
dd asked on 05 Jan 2021, 10:32 PM

I have a grid bound to a collection of objects and i want to have a custom editor for a column. I followed most of the example here:

https://docs.telerik.com/devtools/winforms/controls/gridview/cells/creating-custom-cells

I want to have 2 editors in this cell, one for manual entry and one with a dropdown of values. I have it mostly working, the editors show up during edit mode, the value on the underlying object is correct, but it doesn't show up in the grid for that column. The column is blank. Here is the code.

 

Imports System.ComponentModel
Imports Telerik.WinControls
Imports Telerik.WinControls.UI
 
Public Class test1
    Inherits System.Windows.Forms.Form
 
    'moved designer here for forum post
#Region " Designer "
    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()>
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub
 
    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer
 
    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer. 
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()>
    Private Sub InitializeComponent()
        Dim GridViewTextBoxColumn1 As Telerik.WinControls.UI.GridViewTextBoxColumn = New Telerik.WinControls.UI.GridViewTextBoxColumn()
        Dim GridViewDecimalColumn1 As Telerik.WinControls.UI.GridViewDecimalColumn = New Telerik.WinControls.UI.GridViewDecimalColumn()
        Dim GridViewDecimalColumn2 As Telerik.WinControls.UI.GridViewDecimalColumn = New Telerik.WinControls.UI.GridViewDecimalColumn()
        Dim GridViewDecimalColumn3 As DropdownandSpinEditorColumn = New DropdownandSpinEditorColumn()
        Dim TableViewDefinition1 As Telerik.WinControls.UI.TableViewDefinition = New Telerik.WinControls.UI.TableViewDefinition()
        Me.RadGridView1 = New Telerik.WinControls.UI.RadGridView()
        CType(Me.RadGridView1, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.RadGridView1.MasterTemplate, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'RadGridView1
        '
        Me.RadGridView1.Dock = System.Windows.Forms.DockStyle.Fill
        Me.RadGridView1.Location = New System.Drawing.Point(0, 0)
        '
        '
        '
        GridViewTextBoxColumn1.FieldName = "Id"
        GridViewTextBoxColumn1.HeaderText = "Id"
        GridViewTextBoxColumn1.Name = "Id"
        GridViewTextBoxColumn1.Width = 150
        GridViewDecimalColumn1.DecimalPlaces = 0
        GridViewDecimalColumn1.FieldName = "SpecialNumber1"
        GridViewDecimalColumn1.HeaderText = "Special 1"
        GridViewDecimalColumn1.Name = "SpecialNumber1"
        GridViewDecimalColumn1.Width = 150
        GridViewDecimalColumn2.DecimalPlaces = 0
        GridViewDecimalColumn2.FieldName = "SpecialNumber2"
        GridViewDecimalColumn2.HeaderText = "Special 2"
        GridViewDecimalColumn2.Name = "SpecialNumber2"
        GridViewDecimalColumn2.Width = 150
        GridViewDecimalColumn3.DecimalPlaces = 0
        GridViewDecimalColumn3.FieldName = "ActionNumber"
        GridViewDecimalColumn3.HeaderText = "Action Number"
        GridViewDecimalColumn3.Name = "ActionNumber"
        GridViewDecimalColumn3.Width = 200
        Me.RadGridView1.MasterTemplate.Columns.AddRange(New Telerik.WinControls.UI.GridViewDataColumn() {GridViewTextBoxColumn1, GridViewDecimalColumn1, GridViewDecimalColumn2, GridViewDecimalColumn3})
        Me.RadGridView1.MasterTemplate.ViewDefinition = TableViewDefinition1
        Me.RadGridView1.Name = "RadGridView1"
        Me.RadGridView1.Size = New System.Drawing.Size(800, 450)
        Me.RadGridView1.TabIndex = 0
        '
        'test1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(800, 450)
        Me.Controls.Add(Me.RadGridView1)
        Me.Name = "test1"
        Me.Text = "test1"
        CType(Me.RadGridView1.MasterTemplate, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.RadGridView1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)
 
    End Sub
 
    Friend WithEvents RadGridView1 As Telerik.WinControls.UI.RadGridView
#End Region
 
    Private _list As New BindingList(Of GenData)
 
    Private Sub test1_Load(sender As Object, e As EventArgs) Handles Me.Load
        Dim r As New Random(Now.Millisecond)
        For i = 100 To 110
            _list.Add(New GenData(r) With {.ActionNumber = i})
        Next
        Me.RadGridView1.DataSource = _list
    End Sub
 
    Private Sub RadGridView1_CreateCell(sender As Object, e As GridViewCreateCellEventArgs) Handles RadGridView1.CreateCell
        If TypeOf e.Row.RowInfo Is GridViewDataRowInfo Then
            Select Case e.Column.Name.ToLower()
                Case "actionnumber"
                    e.CellElement = New DropdownandSpinEditorCellElement(e.Column, e.Row)
                    e.CellType = GetType(DropdownandSpinEditorCellElement)
 
            End Select
        End If
    End Sub
 
    Private Sub RadGridView1_CellEndEdit(sender As Object, e As GridViewCellEventArgs) Handles RadGridView1.CellEndEdit
        If TypeOf e.Row Is GridViewDataRowInfo Then
            Dim elementsToRemove As New List(Of RadElement)
            Dim d = e.Row.DataBoundItem
            Console.WriteLine("end edit - " + d.ToString())
            Select Case e.Column.Name.ToLower()
                Case "actionnumber"
                    For Each c In RadGridView1.CurrentCell.Children
                        If TypeOf c Is RadDropDownListElement Then
                            elementsToRemove.Add(c)
                        End If
                    Next
                    For Each i In elementsToRemove
                        RadGridView1.CurrentCell.Children.Remove(i)
                        Console.WriteLine("end edit : removed dropdown")
                    Next
            End Select
        End If
    End Sub
 
    Private Sub RadGridView1_CellBeginEdit(sender As Object, e As GridViewCellCancelEventArgs) Handles RadGridView1.CellBeginEdit
        If TypeOf e.Row Is GridViewDataRowInfo Then
            Dim d = e.Row.DataBoundItem
            Console.WriteLine("begin edit - " + d.ToString())
            Select Case e.Column.Name.ToLower()
                Case "actionnumber"
                    CType(RadGridView1.CurrentCell, DropdownandSpinEditorCellElement).DrawEditor(d)
            End Select
        End If
    End Sub
End Class
 
Public Class GenData
    Private _rand As Random
 
    Public Sub New()
        _rand = New Random(Date.Now.Millisecond)
        SetSpecials()
    End Sub
    Public Sub New(rand As Random)
        _rand = rand
        SetSpecials()
    End Sub
    Public Sub SetSpecials()
        SpecialNumber1 = _rand.Next()
        SpecialNumber2 = _rand.Next()
    End Sub
    Public Overrides Function ToString() As String
        Return NameOf(Id) + " - " + Id + ", " + NameOf(ActionNumber) + " - " + ActionNumber.ToString()
    End Function
    Public Property Id As String = Guid.NewGuid.ToString
    Public Property SpecialNumber1 As Integer = -1
    Public Property SpecialNumber2 As Integer = -1
    Public Property ActionNumber As Integer = -1
End Class
 
Public Class DropdownandSpinEditorCellElement
    Inherits GridDataCellElement
 
    Private _radDropDownElement As RadDropDownListElement
 
    Public Sub New(ByVal column As GridViewColumn, ByVal row As GridRowElement)
        MyBase.New(column, row)
    End Sub
 
    Public Sub DrawEditor(d As GenData)
        _radDropDownElement = BuildDropdown(d)
        Me.Children.Add(_radDropDownElement)
        AddHandler _radDropDownElement.SelectedIndexChanged, AddressOf HandleSelectChanged
    End Sub
 
    Protected Overrides Sub CreateChildElements()
        MyBase.CreateChildElements()
    End Sub
 
    Protected Overrides ReadOnly Property ThemeEffectiveType() As Type
        Get
            Return GetType(GridDataCellElement)
        End Get
    End Property
    Public Overrides Function IsCompatible(ByVal data As GridViewColumn, ByVal context As Object) As Boolean
        Return TypeOf data Is GridViewDecimalColumn AndAlso TypeOf context Is GridDataRowElement
    End Function
 
    Protected Overrides Function ArrangeOverride(ByVal finalSize As SizeF) As SizeF
        Console.WriteLine("children count was : " + Me.Children.Count.ToString)
        If Me.Children.Count = 2 Then
            Dim dropDownWidth As Single = finalSize.Width * 0.5
            Dim dropDownRect As New RectangleF(0, 0, dropDownWidth - 1, finalSize.Height)
            Dim spinEditorRect As New RectangleF(dropDownWidth + 1, 0, finalSize.Width - dropDownWidth - 2, finalSize.Height)
            Me.Children(0).MinSize = New Size(dropDownWidth - 2, 20)
            Me.Children(0).Arrange(dropDownRect)
            Me.Children(1).Arrange(spinEditorRect)
        End If
        Return finalSize
    End Function
 
    Private Function BuildDropdown(ByRef d As GenData) As RadDropDownListElement
        Dim speedDropdown As New RadDropDownListElement()
        speedDropdown.MinSize = New Size(40, 20)
        speedDropdown.MaxSize = speedDropdown.MinSize
        speedDropdown.DropDownWidth = 150
        speedDropdown.DropDownHeight = 130
        speedDropdown.Padding = New Padding(2, 2, 2, 2)
        speedDropdown.Tag = d
        speedDropdown.DataSource = BuildSpecialList(d)
        speedDropdown.DisplayMember = "DisplayValue"
        speedDropdown.ValueMember = "Value"
        speedDropdown.SelectedIndex = 0
        Return speedDropdown
    End Function
 
    Private Sub HandleSelectChanged(sender As Object, e As Data.PositionChangedEventArgs)
        Dim speedDropdown As RadDropDownListElement = CType(sender, RadDropDownListElement)
        Dim d As GenData = speedDropdown.Tag
        Dim data As GenericItem(Of Double) = speedDropdown.SelectedItem.DataBoundItem
        d.ActionNumber = data.Value
    End Sub
 
    Private Function BuildSpecialList(d As GenData) As List(Of GenericItem(Of Double))
        Dim l As New List(Of GenericItem(Of Double))
        Dim g As New GenericItem(Of Double)
        g.DisplayValue = ""
        g.Value = -1
        l.Add(g)
        g = New GenericItem(Of Double)
        g.DisplayValue = d.SpecialNumber1.ToString
        g.Value = d.SpecialNumber1
        l.Add(g)
        g = New GenericItem(Of Double)
        g.DisplayValue = d.SpecialNumber2.ToString
        g.Value = d.SpecialNumber2
        l.Add(g)
        Return l
    End Function
End Class
 
Public Class DropdownandSpinEditorColumn
    Inherits GridViewDecimalColumn
    Public Sub New(ByVal fieldName As String)
        MyBase.New(fieldName)
    End Sub
    Public Sub New()
        MyBase.New()
    End Sub
    Public Overrides Function GetCellType(ByVal row As GridViewRowInfo) As Type
        If TypeOf row Is GridViewDataRowInfo Then
            Return GetType(DropdownandSpinEditorCellElement)
        End If
        Return MyBase.GetCellType(row)
    End Function
End Class
 
Public Class GenericItem(Of ValueType)
    Public Property DisplayValue As String = ""
    Public Property Value As ValueType
    Public Property Data As Object = Nothing
End Class

4 Answers, 1 is accepted

Sort by
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 06 Jan 2021, 08:14 AM

Hello, David,   

Let me start with a brief explanation of the options that you have in RadGridView. I would like to pay attention to the difference between using a custom cell element and a custom editor. Adding elements to the grid cells will display these elements in the cells while they are not in edit mode. Hence, you can almost always see the elements. Once the user tries to edit a cell value, this cell enters edit mode and an editor is being activated considering the value stored in the column. The editor is shown only for a single cell at a time and it is closed once the value is committed or rejected.

Note that RadDropDownListElement and RadTextBoxElement host the MS TextBox. Using controls in grid cells  may slow down the scrolling and will cause visual glitches as they do not support clipping. In such cases, a better option would be using custom editors. Thus, you can construct the desired editor and activate it for the respective cell. 

As to the precise case, I have reviewed the provided code snippet. In the custom GridDataCellElement, the CreateChildElements method is the appropriate place to add elements to the cells which you want to display. Please refer to the following help article which demonstrates a sample approach how to construct custom cells. You can use any elements that you need: 

https://docs.telerik.com/devtools/winforms/controls/gridview/cells/creating-custom-cells 

However, if you want only to show the drop down when the cell is being edited, you can use the EditorRequired event and there specify what editor type to be used. You don't need a custom cell for this. If the default editors don't fit your needs, you can always construct a custom one: https://docs.telerik.com/devtools/winforms/controls/gridview/editors/using-custom-editors 

Feel free to use this approach which suits your scenario best. I hope this information helps. If you need any further assistance please don't hesitate to contact me. 

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
dd
Top achievements
Rank 1
answered on 06 Jan 2021, 03:57 PM

Thank you for looking. What element do i need to add in the CreateChildElements method to make this cell appear like the others? Can you provide an example? I only want to display the value that is on the object while the cell is not in edit mode.

Thanks.

0
Accepted
Dess | Tech Support Engineer, Principal
Telerik team
answered on 07 Jan 2021, 10:26 AM

Hello, David,   

To be honest, I am still not sure whether you want to display the custom element, e.g. RadDropDownListElement, constantly or only while you are editing a cell. If you want to display the element constantly for all cells, then you need to create a custom cell.

However, if you want to display the element only in edit mode, you don't need to create a custom cell element, but just a custom editor and use a default column. Then, replace the default editor with the custom one in the EditorRequired event: https://docs.telerik.com/devtools/winforms/controls/gridview/editors/using-custom-editors

I have prepared a sample project for your reference. Here is illustrated the achieved result: 

 Private Sub RadGridView1_EditorRequired(sender As Object, e As EditorRequiredEventArgs)
     If Me.RadGridView1.CurrentColumn.Name = "ActionNumber" Then
         Dim editor As New MyEditor() 
         e.Editor = editor
     End If

 End Sub

 Private Sub RadGridView1_CellEditorInitialized(sender As Object, e As GridViewCellEventArgs)
     Dim editor As MyEditor = TryCast(e.ActiveEditor, MyEditor)
     If editor IsNot Nothing Then
         editor.speedDropdown.DataSource = BuildSpecialList(DirectCast(Me.RadGridView1.CurrentRow.DataBoundItem, GenData))
         editor.speedDropdown.DisplayMember = "DisplayValue"
         editor.speedDropdown.ValueMember = "Value" 
     End If 
 End Sub


 Private Function BuildSpecialList(d As GenData) As List(Of GenericItem(Of Double))
     Dim l As New List(Of GenericItem(Of Double))
     Dim g As New GenericItem(Of Double)
     g.DisplayValue = ""
     g.Value = -1
     l.Add(g)
     g = New GenericItem(Of Double)
     g.DisplayValue = d.SpecialNumber1.ToString
     g.Value = d.SpecialNumber1
     l.Add(g)
     g = New GenericItem(Of Double)
     g.DisplayValue = d.SpecialNumber2.ToString
     g.Value = d.SpecialNumber2
     l.Add(g)
     Return l
 End Function

 Public Class MyEditor
 Inherits BaseGridEditor
     Dim stack As StackLayoutElement
     Public speedDropdown As RadDropDownListElement
     Dim spinEditor As RadSpinElement
     Protected Overrides Function CreateEditorElement() As RadElement
         stack = New StackLayoutElement
         stack.StretchHorizontally = True
         speedDropdown = New RadDropDownListElement
         spinEditor = New RadSpinElement
         spinEditor.MaxValue = 1000
         stack.Children.Add(speedDropdown)
         stack.Children.Add(spinEditor)

         AddHandler speedDropdown.SelectedIndexChanged, AddressOf speedDropdown_SelectedIndexChanged
         Return stack
     End Function

     Public Overrides Property Value As Object
         Get
             Return spinEditor.Value
         End Get
         Set(value As Object)
             spinEditor.Value = value
         End Set
     End Property

     Private Sub speedDropdown_SelectedIndexChanged(sender As Object, e As UI.Data.PositionChangedEventArgs)
         Dim speedDropdown As RadDropDownListElement = CType(sender, RadDropDownListElement)
         Dim d As GenData = speedDropdown.Tag
         If d IsNot Nothing Then
             Dim data As GenericItem(Of Double) = speedDropdown.SelectedItem.DataBoundItem
             d.ActionNumber = data.Value
         End If 
     End Sub

 End Class

Note that this is just a sample approach and it may not cover all possible cases. Please give the sample project a try and see how it works for your case. Feel free to modify and extend it in a way which suits your custom requirements best.  

Should you have further questions please let me know.

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
dd
Top achievements
Rank 1
answered on 07 Jan 2021, 05:31 PM
hi dess, that is perfect! this is a much better way to do it. thank you for the clean solution.
Tags
GridView
Asked by
dd
Top achievements
Rank 1
Answers by
Dess | Tech Support Engineer, Principal
Telerik team
dd
Top achievements
Rank 1
Share this question
or