Search code examples
vb.netwebformsrepeater

No default member found for type Parcel


This is a duplicate as commented below but I think we need to keep it around. I did find the duplicate in my searching for help before posting. The explanation here was easier for me to follow than on the duplicate.

When I run the below code I'm getting the Error "No default member found for type Parcel" right after it runs the ParcelsRepeater.DataSource = Split.Parcels command. The error message appears to be highlighting <%#Container.DataItem("PIN")%> in the aspx code.

It never appears to hit the ItemDataBound event.

Imports System.Linq


Public Class SplitCreateParcels
Inherits System.Web.UI.Page

Public Class SplitParcel

    Public Sub New()
        Parcels = New List(Of Parcel)
    End Sub


    Public Property Parcels As List(Of Parcel)

End Class

Public Class Cat
    Public Property Category As String
End Class

Public Class Parcel

    Public Sub New()
        Categories = New List(Of Cat)
    End Sub
    Public Property PIN As String
    Public Property Categories As List(Of Cat)
End Class

Public Property _Split As SplitParcel


Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    Dim Split As New SplitParcel
    Dim Parcel1 As New Parcel
    Dim Parcel2 As New Parcel


    Split.Parcels.Add(Parcel1)
    Split.Parcels.Add(Parcel2)

    Parcel1.PIN = "Test1"
    Parcel1.Categories.Add(New Cat With {.Category = "1"})
    Parcel1.Categories.Add(New Cat With {.Category = "2"})

    Parcel2.PIN = "Test2"
    Parcel2.Categories.Add(New Cat With {.Category = "3"})
    Parcel2.Categories.Add(New Cat With {.Category = "4"})

    ParcelsRepeater.DataSource = Split.Parcels
    ParcelsRepeater.DataBind()


End Sub

Protected Sub ParcelsRepeater_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
    If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
        Dim ParentDataItem As Parcel = DirectCast(e.Item.DataItem, Parcel)


        Dim ChildRepeater As Repeater = DirectCast(e.Item.FindControl("IntegerRepeater"), Repeater)
        ChildRepeater.DataSource = ParentDataItem.Categories
        ChildRepeater.DataBind()



    End If
End Sub
End Class



<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="SplitCreateParcels.aspx.vb" Inherits="UADWeb.SplitCreateParcels" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

        <asp:Repeater ID="ParcelsRepeater" runat="server"  OnItemDataBound="ParcelsRepeater_ItemDataBound">
            <ItemTemplate>
                <%#Container.DataItem("PIN")%>
                <asp:Repeater runat="server" ID="IntegerRepeater">
                    <ItemTemplate>
                        <%#Container.DataItem("Category")%></br>
                    </ItemTemplate>
                </asp:Repeater>
            </ItemTemplate>
        </asp:Repeater>
    </div>
    </form>
</body>
</html>

Solution

  • I believe that your problem is this line:

    <%#Container.DataItem("PIN")%>
    

    This occurs before ParcelsRepeater_ItemDataBound as it is handled as part of the databinding.

    As you've already shown in your code, you need to cast your DataItem to it's proper type to access the properties. The following should work:

    <%#DirectCast(Container.DataItem, [Namespaced Path To your Type].Parcel).PIN%>
    

    It is necessary to provide the full path to your Parcel type because of differences in how code is handled in the codebehind vs mark-up. For an alternative to that syntax you can view this Q&A.

    As a different solution, you can just add a literal to your item template and populate it's text in code-behind:

    <asp:Repeater ID="ParcelsRepeater" runat="server" 
      OnItemDataBound="ParcelsRepeater_ItemDataBound">
      <ItemTemplate>
        <asp:Literal Text="" ID="Pin" runat="server" /> 
        ...
    

    then with ParcelsRepeater_ItemDataBound

    Dim ParentDataItem = DirectCast(e.Item.DataItem, Parcel)
    Dim PinLiteral = DirectCast(e.Item.FindControl("Pin"), Literal)
    PinLiteral.Text = ParentDataItem.PIN
    ...