Search code examples
.netvb.netwinformsdata-bindingcurrencymanager

Getting base field type when databinding to a Decimal (or Object) property


I've got a custom NumericEditor control that has a nullable Decimal property called Value. When I bind a data field to Value, I'd like to retrieve the underlying Type of the data that's bound, so that I can restrict the use of decimal places if the source field is an integral data type.

I figure I'd have to do this in the BindingContextChanged event, but how do I get the Type of the data field from the binding itself? My Google-Fu is failing me at the moment.

In short, I'm looking for something like the GetValueType method mentioned in the following question: Simple databinding - How to handle bound field/property change. Winforms, .Net

I imagine this method would also be handy if the Value property was an Object.


Solution

  • I've come up with the following solution:

    Private Sub NumericEditor_BindingContextChanged(sender As Object, e As EventArgs) Handles Me.BindingContextChanged
       If DataBindings.Count > 0 AndAlso DataBindings.Item("Value") IsNot Nothing Then
          Dim myPropDescs As PropertyDescriptorCollection = DataBindings.Item("Value").BindingManagerBase.GetItemProperties
          Dim propertyName As String = DataBindings.Item("Value").BindingMemberInfo.BindingField
          Dim bindingType As Type = myPropDescs.Find(propertyName, False).PropertyType
    
          Select Case bindingType
             Case GetType(SByte)
                DecimalPlaces = 0
                MinimumValue = SByte.MinValue
                MaximumValue = SByte.MaxValue
             Case GetType(Byte)
                DecimalPlaces = 0
                MinimumValue = Byte.MinValue
                MaximumValue = Byte.MaxValue
             Case GetType(Int16)
                DecimalPlaces = 0
                MinimumValue = Int16.MinValue
                MaximumValue = Int16.MaxValue
             Case GetType(UInt16)
                DecimalPlaces = 0
                MinimumValue = UInt16.MinValue
                MaximumValue = UInt16.MaxValue
             Case GetType(Int32)
                DecimalPlaces = 0
                MinimumValue = Int32.MinValue
                MaximumValue = Int32.MaxValue
             Case GetType(UInt32)
                DecimalPlaces = 0
                MinimumValue = UInt32.MinValue
                MaximumValue = UInt32.MaxValue
             Case GetType(Int64)
                DecimalPlaces = 0
                MinimumValue = Int64.MinValue
                MaximumValue = Int64.MaxValue
             Case GetType(UInt64)
                DecimalPlaces = 0
                MinimumValue = UInt64.MinValue
                MaximumValue = UInt64.MaxValue
             Case GetType(Single), GetType(Double), GetType(Decimal)
                MinimumValue = Decimal.MinValue
                MaximumValue = Decimal.MaxValue
          End Select
       End If
    End Sub
    

    It's a little repetitive and therefore not that elegant, but it works. (My actual code also has checks when setting MinimumValue and MaximumValue in case the developer has already set those properties, ensuring the developer's settings are not overridden if they are still valid.)