The previous sample showed a basic example of using
anonymous types to custom-shape the output of a LINQ query. The below sample
provides a richer and more practical scenario. It transforms our list of
cities into a hierarchical result collection – where we group the results
around countries using an anonymous type that we define that contains the
country name, a sub-collection list of city details, and the sum of the total
distance of all cities within the country (computed using a lambda expression
like we demonstrated in step5 above):
Listing 17
using System;
using System.Web.UI;
using System.Query;
public partial class Step7 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TravelOrganizer travel = new TravelOrganizer();
GridView1.DataSource = from location in travel.PlacesVisited
group location by location.Country into loc
select new {
Country = loc.Key,
Cities = loc,
TotalDistance = loc.Sum(dist => dist.Distance)
};
GridView1.DataBind();
}
}
The GridView on our .aspx page is then defined like so:
Listing 18
<%@Page Language="C#" AutoEventWireup="true" CodeFile="Step7.aspx.cs"
Inherits="Step7" %>
<html>
<body>
<form id="form1" runat="server">
<div>
<h1>Groupings with Anonymous Classes</h1>
<asp:GridView ID="GridView1"
AutoGenerateColumns="false" runat="server">
<Columns>
<asp:BoundField HeaderText="Country" DataField="Country" />
<asp:TemplateField HeaderText="Cities">
<ItemTemplate>
<asp:BulletedList ID="BulletedList1" runat="server"
DataSource='<%#Eval("Cities")%>'
DataValueField="City"/>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Total Distance"
DataField="TotalDistance" />
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>
Notice how I’ve added a GridView templatefield column for
the “Cities” column – and within that I’ve then added an
<asp:bulletedlist> control (a new control built-in with ASP.NET 2.0) that
databinds its values from the cities property of the hierarchical result we
created using our LINQ query above. This generates output like so:
Figure 8
<img border=0 width=535 height=581src="/ArticleFiles/922/image007.jpg">
Note that all of the databind syntax and hierarchical
binding support in the .aspx page above is fully supported in ASP.NET 2.0 today
– so you can use this same technique with any existing app you have now. What
is new (and I think very cool) is the data shaping capabilities provided by
anonymous types and LINQ – which makes binding hierarchical data against
ASP.NET controls very easy.