Asp – How to Bind a custom class with no strongly typed properties

asp.netdata-bindingnetvb.net

hey guys, here are my requirements:

I need a simple class with only one Public property and no Public methods (the final Class will be more complex, but for testing this is all I need)

The Property is "Item" and takes a "String" as a parameter. It returns a "String" based on the parameter.

I then want be able to add instances of this object to a List or Array, and then Bind it to a Repeater or a ListView

…most importantly, I want to be able to then refer to values in my simple Class via the Eval function:

<%# Eval("**SomeIDString") %>**.

Here are my problems:

  1. I can't Bind at all unless I declare the Item property as the Default property…why?

  2. When I use "Eval", I get an error in the lines of "[some property] does not exists". indeed it doesn't, because everything is accessed via the Item property. it then does works if I replace "Eval" with "Container.DataItem".

So, is there a way to use Eval instead of Container.DataItem? I would rather not have my class inherit any other classes because I want to keep it clean from supurfulous properties and/or methods.

Are there interfaces I need to implement?

Also, the reason I want to use Eval, is that as much as possible, I want to make the use of this Class simple, so the coder doesn't need to worry about special cases. I just want it to work, much like the DataTable Class, but with a much simpler, lighter-weight implementation.

cheers

Best Answer

Your problem arises from the use of a parameterized property (that too, one that use a string parameter). Parameterized properties usually make sense only when they are default properties and expose an indexed collection of some object. (See C# indexers) C# allows only allows the indexer to be parameterized while VB is more relaxed on this restriction.

Assuming a class such as the following:

Public Class TempClass
  Private strItem As New StringDictionary()

  Public Property Item(ByVal s As String) As String
    Get
      Return strItem(s)
    End Get
    Set(ByVal value As String)
      strItem(s) = value
    End Set
  End Property
End Class

The Eval function requires the name of a valid public property. When you use a parameterized property, the signature is different from what you can specify within an Eval function. If you use the following syntax :

<asp:Label ID="lbl1" runat="server" Text='<%#Eval("Item(""a"")")%>' />

... It doesn't resolve.

Your solution is threefold:

a. Evaluate why you need to have this property parameterized. It would make sense to me if it is passed a key that it can look up from a collection.

b. Instead of using the Eval keyword, use the expanded syntax and perform casting manually:

<asp:Label ID="lbl1" runat="server" Text='<%#CType(Container.DataItem, MyCustomClass).Item("a") %>' />

c. Also think about how you would pass a different key to each record in the Repeater. This might be ideal if an integer index is accepted instead so that we can link it to the row number of the repeater. Modifying the above class as follows:

Public Class TempClass
  Private strItems(3) As String

  Public Sub New()
    strItems(0) = "x"
    strItems(1) = "y"
    strItems(2) = "z"
  End Sub

  Public Property Items(ByVal i As Integer) As String
Get
      Return strItems(i)
End Get
Set(ByVal value As String)
      strItems(i) = value
End Set
  End Property
End Class

We can then render the appropriate item in the array as follows:

<asp:Label ID="lbl1" runat="server" Text='<%#CType(Container.DataItem, TempClass).Items(Container.ItemIndex) %>' />

Edited upon request:


d) Class modifed to use a Default property:

Default Public Property Item(ByVal s As String) As String
  Get
    Return strItem(s)
  End Get
  Set(ByVal value As String)
    strItem(s) = value
  End Set
End Property

Databinding now becomes:

<span><%#Eval("(a)")%></span>
<asp:Label ID="lbl2" runat="server" Text='<%#Eval("(b)")%>' />