Search code examples
vb.netpropertiesdatagridviewcolumn

How can I make custom DataGridViewColumn properties work at design time?


Recently I've written a custom DataGridViewColumn to host a progress bar. The column class itself has a property that I'd like to propagate to all the cells of the column. I use this code to implement it:-

<DefaultValue(5I)> _
Public Property BlockWidth() As Integer
    Get
        Return _blockWidth
    End Get
    Set(ByVal value As Integer)
        _blockWidth = value

        Me.ColumnCells.ForEach(Sub(cell) cell.BlockWidth = value)
    End Set
End Property

And this:-

Private ReadOnly Property ColumnCells As IEnumerable(Of DataGridViewProgressBarCell)
    Get
        If Me.DataGridView IsNot Nothing Then
            Return Me.DataGridView.Rows.
                Cast(Of DataGridViewRow).
                Where(Function(r) TypeOf r.Cells.Item(Me.Index) Is DataGridViewProgressBarCell).
                Select(Function(r) DirectCast(r.Cells.Item(Me.Index), DataGridViewProgressBarCell))
        Else
            Return New DataGridViewProgressBarCell() {}
        End If
    End Get
End Property

Now this works at runtime. If I change the BlockWidth property of a column at runtime, all the cells of the column will change to reflect the property change but I cannot seem to get this to work at design time. At design time the cell doesn't change, the property change persists but the cell doesn't change. I've tried all manner of trickery and it refuses to work. Please can anyone tell me what I'm doing wrong ?


Solution

  • Nevermind. I figured it out. I had to set the BlockWidth property on the cell template(through the CellTemplate property of the column class) object passed to the constructor of the column object. Also, I forgot to clone the BlockWidth property on the progress bar's cell class.

    <DefaultValue(5I)> _
    Public Property BlockWidth() As Integer
        Get
            Return _blockWidth
        End Get
        Set(ByVal value As Integer)
            _blockWidth = value
    
            'For changes to be reflected at runtime
            Me.ColumnCells.ForEach(Sub(cell) cell.BlockWidth = value)
    
            'For changes to be reflected at design time
            Me.Template.BlockWidth = _blockWidth
    
            If Me.DataGridView IsNot Nothing Then
                Me.DataGridView.InvalidateColumn(Me.Index)
            End If
        End Set
    End Property
    

    Thanks you all for your comments and answers. :)