views:

775

answers:

3

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

A: 

Unless you use an object data source you can't use Eval on a class.

"Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control."
Jonathan Parker
That is an erroneous statement. Eval() has got nothing exclusively to do with the ObjectDataSource control. You can always bind a control to an IEnumerable class.
Cerebrus
yeah, just to clarify, my class is going in a list, and then is being assigned to a repeater's datasource.
andy
Oh well, the above error message is from ASP.NET. That's just how I interpreted the message.
Jonathan Parker
+1  A: 

there are sooooo many tutorials on this Andy! Did you look/search for them?

what you are saying is that you just want to create an Object (class) and use that as a DataSource of a Data Control, you can always use ObjectDataSource if you don't want to do things in the code.

balexandre
hey balexande, thanks for your help. yeah, I searched but came up with nothing that deals with the particularities of my issue. Also, I wonder if you misunderstood my problem, as the benefits of the ObjectdataSource are irrelevant.
andy
Sure I did... the tutorials I mean are regarding Data Objects, like building a class that you can bind to anything, I particular love the ones that contain 3.5SP1 tricks on them, just download this code and find for your self, see the SalesPerson/DAO objects: http://is.gd/mPXv
balexandre
cool! will check it out, thanks man
andy
+1  A: 

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)")%>' />
Cerebrus
Thanks Cerebrus. So I guess the bottom line is, I can't use the simpler Eval. You're right, I need a parameterized property. I guess what I was going for was a behaviour similar to a DataRow within a DataTable, where you can use Eval. But then the DataRow requires a lot of overhead...?
andy
Cerebrus, as a follow up question: When I try to Bind the same list of my simple Classes to a gridview with autogenerated columns, I get "grid did not have any properties or attributes". Whats the work around...do i have to give in to a DataTable? cheers
andy
@Andy: The Datarow behaviour is possible because it exposes the Value in the passed ColumnName as the Default property. If you modify the above class to mimic that, then you don't need to use the "Item" propertyname. Therefore, you can use Eval("a") in that case.
Cerebrus
@Cerebrus: Thanks so much man. I kinda understand, but not completely sure how to implement. Could you possibly post an example of the above class but with the mod? I'll try it out here and see how I go.Thanks again
andy
Done. Hope that helps! ;-)
Cerebrus