Search code examples
vb.netdictionarydevexpressdevexpress-windows-ui

Bind a detail report to a class model with properties stored in a Dictionary (VB.NET, Devexpress)


I'm trying the example from Devexpress

Dim binding As New XRBinding("Text", dsProducts1, "Products.UnitPrice")

But my models does not have their properties explicitly written in their class. It would take a method GetProperty("column_name_here") to get it's data. I'm wondering if the 3rd parameter of XRBinding can be a method? Like:

Dim binding As New XRBinding("Text", dsProducts1, product.GetProperty("name"))

Additional Info:

All of my model classes extends this Dao class which is responsible in getting data in the database. The Dao class have a protected variable as a Dictionary(Of String, Object) to store the values (key = column name, value = column row value) from the database.

Now when I want to get something in the database, I only call

Dim user As New User // this class extends the Dao class

Dim userId = user.GetProperty("id") // Method to get the value from Dictionary, first parameter is the Dictionary key or column name from the DB

I made this so that I wont have to create every model class and set the properties of that class, as it is kinda cumbersome.


Solution

  • It seems that there are no way to bind to some method. I suggest you to take a look at ExpandoObject dynamic class. The members of this class can be added at runtime. This class implements IDictionary(Of String, Object) interface which you can use to generate properties from your Dictionary(Of String, Object).

    Here is example:

    Example of base Dao class implementation with protected Dictionary(Of String, Object) property:

    Public Class Dao
        Private _values As Dictionary(Of String, Object)
    
        Public Sub New()
            _values = New Dictionary(Of String, Object)
        End Sub
    
        Public Overridable Sub Fill(index As Integer)
            _values.Clear()
    
            _values.Add("ID", index)
            _values.Add("Product", "Banana " & index)
            _values.Add("Price", 123.45 + index)
        End Sub
    
        Protected ReadOnly Property Values As Dictionary(Of String, Object)
            Get
                Return _values
            End Get
        End Property
    End Class
    

    Example of Dao class descendant with DynamicValues property which returns ExpandoObject based on Dictionary(Of String, Object) (you must omit the type of property):

    Public Class DynamicDao
        Inherits Dao
    
        Private _dynamicValues As ExpandoObject
    
        Public Overrides Sub Fill(index As Integer)
            MyBase.Fill(index)
    
            _dynamicValues = New ExpandoObject()
    
            Dim keyValues = DirectCast(_dynamicValues, IDictionary(Of String, Object))
    
            For Each pair In Values
                keyValues.Add(New KeyValuePair(Of String, Object)(pair.Key, pair.Value))
            Next
        End Sub
    
        Public ReadOnly Property DynamicValues ' <= There is no type. In hint is displayed «As Object».
            Get
                Return _dynamicValues
            End Get
        End Property
    End Class
    

    Usage of DynamicDao class in XtraReport:

    Dim list = New List(Of DynamicDao)
    
    For index% = 0 To 9
        Dim dao = New DynamicDao()
        dao.Fill(index%)
    
        list.Add(dao)
    Next
    
    Dim labelID = New XRLabel()
    labelID.DataBindings.Add(New XRBinding("Text", Nothing, "DynamicValues.ID"))
    
    Dim labelProduct = New XRLabel()
    labelProduct.DataBindings.Add(New XRBinding("Text", Nothing, "DynamicValues.Product"))
    labelProduct.LeftF = 50
    
    Dim labelPrice = New XRLabel()
    labelPrice.DataBindings.Add(New XRBinding("Text", Nothing, "DynamicValues.Price"))
    labelPrice.LeftF = 150
    
    Dim detail = New DetailBand()
    detail.Controls.Add(labelID)
    detail.Controls.Add(labelProduct)
    detail.Controls.Add(labelPrice)
    
    Dim report = New XtraReport()
    report.Bands.Add(detail)
    report.DataSource = list
    
    report.ShowRibbonPreview()