views:

1386

answers:

3

I'm having trouble figuring out how to bind a custom IList to a gridview. The IList contains another custom IList. I need to bind a property from this IList to the gridview.

public class Seminar : BusinessObject
{
    private string _description = String.Empty;
    private List<User> _attendees;

    public string Description {get {return _description;} set {_description = value;}}
    public List<User> Attendees {get {return _attendees;} set {_attendees = value;}}
}

public class User : BusinessObject
{
    private string _name = String.Empty;
    public string Name { get { return _name; } set { _name = value; } }
}

Backend page.aspx.cs:

List<Seminar> seminarList = SeminarManager.Get(id);
gridSeminars.DataSource = seminarList;
gridSeminars.DataBind();

Frontend page.aspx:

<asp:GridView ID="gridSeminars" runat="server">
<Columns>
    <asp:BoundField DataField="Id" />
    <asp:BoundField DataField="Description" />
    <asp:BoundField DataField="Name" />
</Columns>
</asp:GridView>

The problem is with populating the "Name" field in the gridview. All suggestions are welcome.

A: 

Have you tried,

Attendees.Name

Edit: Attendees is an IEnumerable itself. The above suggestion only works with Attendee.Name

If you wan´t to display all the attendees you need to make a templatefield and maybe use a repeater or something...something like:

   <asp:TemplateField>
        <ItemTemplate>
            <asp:Repeater runat="server" DataSource='<%# Eval("Attendees") %>'>
                <ItemTemplate>
                    <tr>
                    <td>
                    Name
                    </td>
                    <td>
                        <%# Eval("Name")%>
                    </td>
                    </tr>
                </ItemTemplate>
            </asp:Repeater>
        </ItemTemplate>
    </asp:TemplateField>
Johan Leino
There is no Name property on the Attendees property itself since it's of type IEnumerable, but the nested controls solution is a good one.
Lance Harper
A: 

Johan's answer is a good one, specifically the part about how you are trying to bind a collection to a column that is expecting something that can be converted to a string.

Another option would be to put a TemplateField that contains the bindable control (Repeater, another GridView, etc.) you choose to use and binding the DataSource property to the Attendees property of your business object.

Also, I don't if you're married to the idea of using a GridView, but in cases like these where you need more control of the layout, I would suggest the new ListView (.NET 3.5) control, or lately I've just been using nested repeaters so I can have more refined control of the layout I am trying to generate.

Hope this helps.

Lance Harper
A: 

I'm assuming you want to flatten the hierarchy and display one row for every user. If you have access to Linq, you can use this:

List<Seminar> seminarList = SeminarManager.Get(id);

gridSeminars.DataSource = from seminar in seminarList // loop through all of the seminars in the list
                          from user in seminar.Attendees // loop through all of the users in the current seminar
                          select new // create a new, flattened object to bind to.
                          {
                            seminar.Id,
                            seminar.Description,
                            user.Name
                          };

gridSeminars.DataBind();

http://weblogs.asp.net/zeeshanhirani/archive/2008/03/26/select-many-operator-part-1.aspx

Greg
This looked like it would solve my problem quickly, but I kept running into a syntax error that wouldn't let me write the line "from user in seminar.Attendees". I need to figure out this LINQ stuff!
Brian
I think I forgot a semicolon. Does it work now?
Greg