Inspecting the DataBindings property

I am trying to discover the properties of the components on a Form using automation, and all goes well until I get to the DataBindings property. It displays as a System.Windows.Forms.ControlBindingCollection. I can get ahold of this object and get its BindingSource, but I cannot figure out how to get ahold of the BindingSource.DataSource. I know it's bound to an object and I can see the correct object in the debugger, but when I call BindingSource.DataSource.getType(), I just get a System.RuntimeType object.

So, is there an easier way to introspect the properties of DataBindings, and if not, how can I discover the type of the object bound to the BindingSource

Thanks in advance for any help.

Herman Post

public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)

{

handled = false;

if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)

{

if(commandName == "DataBindingExample.Connect.DataBindingExample")

{

IDesignerHost host;

host = (IDesignerHost)_applicationObject.ActiveWindow.Object as System.ComponentModel.Design.IDesignerHost;

PropertyDescriptorCollection propertyDescriptorCollection;

String message = "";

foreach (Component component in host.Container.Components)

{

message += "**************************************************\n";

message += "Component Type: " + component.GetType() + "\n";

message += "*************** Properties follow ***************" + "\n";

propertyDescriptorCollection = TypeDescriptor.GetProperties(component);

foreach (PropertyDescriptor property in propertyDescriptorCollection)

{

message += property.Name + " : " + property.GetValue(component) + "\n";

ControlBindingsCollection cbc;

if (property.Name == "DataBindings")

{

cbc = (System.Windows.Forms.ControlBindingsCollection)property.GetValue(component);

System.Collections.IEnumerator itor = cbc.GetEnumerator();

while (itor.MoveNext())

{

Trace.WriteLine("\nComponent: " + component.ToString()) ;

Binding binding = (Binding)itor.Current;

String debug = "Bound Property: " + binding.PropertyName + "\nDataSource: " + binding.DataSource.ToString() +

"\nBindingMemberInfo.BindingField: " + binding.BindingMemberInfo.BindingField;

BindingSource bindingSource = (BindingSource)binding.DataSource;

// bindingSource.DataSource.getType() is System.RuntimeType

Trace.WriteLine(debug);

}

}

}

}

//MessageBox.Show(message);

handled = true;

return;

}



Answer this question

Inspecting the DataBindings property

  • Frank J DeFalco

    Hi,

    I finally have tested some code with an add-in and:

    - For VS.NET 2003, I get a Dataset type, not a System.RuntimeType

    - For VS 2005, I get a BindingSource type (which is a new type in .NET 2.0), not a System.RuntimeType.

    In both cases I bound the Text and Tag properties of the DataBindings property of a form to some fields of a Dataset that I added to the form.

    So, I don’t know why you get a RuntimeType. Can you explain step by step what binding you did in the form

    My (VB.NET) code is:

    _applicationObject = CType(application, DTE)
    objIDesignerHost = CType(_applicationObject.ActiveWindow.Object, IDesignerHost)
    For Each objComponent In objIDesignerHost.Container.Components
    For Each objPropertyDescriptor As PropertyDescriptor In TypeDescriptor.GetProperties(objComponent)

    If objPropertyDescriptor.Name = "DataBindings" Then
    objControlBindingsCollection = DirectCast(objPropertyDescriptor.GetValue(objComponent), ControlBindingsCollection)

    For Each objBinding In objControlBindingsCollection
    objObject = objBinding.DataSource
    Next
    End If
    Next
    Next

    --
    Best regards,
    Carlos J. Quintero
    MZ-Tools: Productivity add-ins for Visual Studio
    You can code, design and document much faster:
    http://www.mztools.com



  • _MRCHINGON_

    The Fullname property still comes thru as System.RuntimeType.

    Type type = (Type)bindingSource.DataSource.GetType();

    // type.FullName is System.RuntimeType


  • haricharan

    Hi Herman,

    I have not tested it in your case, but try adding a reference to the Microsoft.VisualBasic assembly and use:

    Microsoft.VisualBasic.Information.Typename(bindingSource.DataSource).

    That little gem function of Visual Basic should return a string with the actual type name of an Object and give you a clue about what to cast it to (then you can remove the VisualBasic assembly). At least it works with System.__ComObject when using COM Interop....

    --
    Best regards,
    Carlos J. Quintero
    MZ-Tools: Productivity add-ins for Visual Studio
    You can code, design and document much faster:
    http://www.mztools.com



  • MAOWEIJUN

    Thanks for taking the time to look into this Carlos - I appreciate it.

    I bind to a type that exists in the project. I created a simple Person class with a name, birthday and gender. I can see the BindingSource object fine. It is the BindingSource.DataSource property that is coming back as a RuntimeType. In the debugger I can see the that BindingSource.DataSource contains the assembly and class name of the object I'm bound to (Person), but I can't figure out how to cast it in code. So to continue your sample:

    For Each objBinding In objControlBindingsCollection
    objBindingSource = objBinding.DataSource

    Type type = objBindingSource.DataSource.GetType(); ' I can see Form1.Person here as the binding

    MessageBox.Show(type.FullName); ' System.RuntimeType

    Next

    I confess I am somewhat new to C# (switching from Java), so there may be something here I am overlooking.

    Thanks,

    Herman Post


  • Jesse - MSFT

    > I confess I am somewhat new to C# (switching from Java),
    >
    so there may be something here I am overlooking.

    And I was not that familiar with databinding or binding to objects. The behavior is the expected, you get a RuntimeType as BindingSource.DataSource when binding to an object (instead of to a dataset). As I said, RuntimeType is an internal class of the .NET Framework but you can cast it to the public System.Type. This class represents the type of an object and it is the central class of Reflection, a part of the .NET framework that allows you to introspect the properties, methods, etc of the class (type) of an object. I think that Java has this capability as well. 

    For example, if you have:

    Dim objPerson As Person
    Dim objType As System.Type

    objPerson = New Person()
    objType = objPerson.GetType()

    then, using objType, you can discover all the properties, methods, fields, etc. of the Person object.

    So, returning to your case, using System.Type you can know whatever you want from the class bound to your control. For example:

       Public Sub OnConnection(ByVal application As Object, ByVal connectMode As ext_ConnectMode, ByVal addInInst As Object, ByRef custom As Array) Implements IDTExtensibility2.OnConnection

          Dim objIDesignerHost As System.ComponentModel.Design.IDesignerHost
          Dim objControlBindingsCollection As ControlBindingsCollection
          Dim objBinding As Binding
          Dim objBindingSource As BindingSource
          Dim objType As System.Type

          Try


             _applicationObject = CType(application, DTE2)
             objIDesignerHost = TryCast(_applicationObject.ActiveWindow.Object, System.ComponentModel.Design.IDesignerHost)

             For Each objComponent As Component In objIDesignerHost.Container.Components

                For Each objPropertyDescriptor As PropertyDescriptor In TypeDescriptor.GetProperties(objComponent)

                   If objPropertyDescriptor.Name = "DataBindings" Then

                      objControlBindingsCollection = DirectCast(objPropertyDescriptor.GetValue(objComponent), ControlBindingsCollection)

                      For Each objBinding In objControlBindingsCollection

                         objBindingSource = DirectCast(objBinding.DataSource, BindingSource)

                         If TypeOf objBindingSource.DataSource Is System.Type Then

                            objType = DirectCast(objBindingSource.DataSource, System.Type)

                            MessageBox.Show("Control property '" & objBinding.PropertyName & "' is bound to object property '" & objBinding.BindingMemberInfo.BindingMember & "' of class '" & objType.FullName & "' of assembly '" & objType.Assembly.FullName & "'")

                         End If

                      Next

                   End If

                Next

             Next

          Catch ex As Exception

          End Try

       End Sub

    Notice that your confusion was that you were using BindingSource.DataSource.GetType() instead of casting BindingSource.DataSource to Type to get the Type of your bound class. In your case, BindingSource.DataSource is already the Type that you were looking for to inspect. Using GetType on a Type class is like getting metadata from metadata, no point at all in most cases...

    I hope you understand the thing now. Let me know otherwise.

    --
    Best regards,
    Carlos J. Quintero
    MZ-Tools: Productivity add-ins for Visual Studio
    You can code, design and document much faster:
    http://www.mztools.com



  • mark87544

    System.RuntimeType is an internal (Friend) class inside the mscorlib.dll assembly which inherits from System.Type (which is abstract) and implements its methods.

    I am not sure if you are familiar with Reflection, but given an object "o", o.GetType() returns an instance of System.RuntimeType.

    What does the FullName property return for that System.RuntimeType instance

    --
    Best regards,
    Carlos J. Quintero
    MZ-Tools: Productivity add-ins for Visual Studio
    You can code, design and document much faster:
    http://www.mztools.com



  • Anssi Lehtonen

    Ah - that last piece was it - casting Datasource to Type.

    Thanks much for your help.

    Herman Post


  • fbrian

    Thanks for responding. Unfortunately, that returns the same thing as Object.getType(): System.RuntimeType, which curiously is not documented in help. Is there another way to get at the values of the DataBindings property, rather than going after the ControlBindingsCollection

    Thanks,

    Herm


  • Inspecting the DataBindings property