以下是我傾向於解決問題是這樣的:
手動拉我們要顯示的數據(調用庫方法,不使用的ObjectDataSource這樣做)。爲了提高效率,一個大查詢返回非規格化記錄通常很有意義,每個記錄包含所有需要的列(例如:SELECT TimeSlot, CustomerName, ContractorName FROM (joins go here) ...
)
創建一個自定義集合類,它將數據放入一個簡單的格式到數據綁定。 「易於數據綁定」通常意味着數據的組織順序與您要顯示的順序相同。您也可能需要進行黑客行爲,例如,使所有行的長度相同,以便每行綁定相同數量的表格單元格。
在您的數據綁定表達式中,將Container.DataItem轉換爲您需要的任何類型,以便提取該類型的屬性。這還具有在編譯時使用拼寫錯誤的數據綁定表達式失敗的附加優勢,而不是等到運行時才能找到錯誤。
嵌套,嵌套模板控制(如:中繼器)的DataSource屬性設置爲父母的財產的Container.DataItem
爲標題行,這裏有一個竅門:將頭碼直接進入ItemTemplate,並使用Container.ItemIndex == 0知道何時顯示標題行。由於只有Repeater(但不是ListView)支持ItemIndex屬性,因此我傾向於使用Repeater而不是ListView來執行大多數只讀數據綁定任務。這就是爲什麼我在下面的代碼示例中更改了您的ListView以使用Repeater。將Index或RowNumber屬性添加到上述自定義數據綁定類中也可以做到這一點,但這很難。
總的想法是,你要推的大量情報,儘可能出你的數據綁定代碼並進入你的頁面的實際方法(或代碼隱藏)代碼,這是更容易編寫和調試。
下面是一個工作示例(將您的類和存儲庫類嘲笑起來),讓您知道我在說什麼。你應該能夠適應你的情況。
<%@ Page Language="C#"%>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Linq" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
public class Person // replace with your class
{
public string person_name {get; set;}
}
public class Repository // replace with your class
{
public static IEnumerable<Record> GetCustomerByDateCategory()
{
// fake some data
return new Record[]
{
new Record { Time = new DateTime(2000, 1, 1, 8, 0, 0), Contractor = new Person {person_name = "Joe the Plumber"}, Customer = new Person {person_name = "Joe Smith"} },
new Record { Time = new DateTime(2000, 1, 1, 8, 30, 0), Contractor = new Person {person_name = "Bob Vila"}, Customer = new Person {person_name = "Frank Johnson"} },
new Record { Time = new DateTime(2000, 1, 1, 8, 30, 0), Contractor = new Person {person_name = "Mr. Clean"}, Customer = new Person {person_name = "Elliott P. Ness"} },
};
}
public class Record // replace this class with your record's class
{
public DateTime Time {get; set;}
public Person Contractor { get; set; }
public Person Customer { get; set; }
}
}
// key = time, value = ordered (by contractor) list of customers in that time slot
public class CustomersByTime : SortedDictionary<DateTime, List<Person>>
{
public List<Person> Contractors { get; set; }
public CustomersByTime (IEnumerable <Repository.Record> records)
{
Contractors = new List<Person>();
foreach (Repository.Record record in records)
{
int contractorIndex = Contractors.FindIndex(p => p.person_name == record.Contractor.person_name);
if (contractorIndex == -1)
{
Contractors.Add(record.Contractor);
contractorIndex = Contractors.Count - 1;
}
List<Person> customerList;
if (!this.TryGetValue(record.Time, out customerList))
{
customerList = new List<Person>();
this.Add(record.Time, customerList);
}
while (customerList.Count < contractorIndex)
customerList.Add (null); // fill in blanks if needed
customerList.Add (record.Customer); // fill in blanks if needed
}
MakeSameLength();
}
// extend each list to match the longest one. makes databinding easier.
public void MakeSameLength()
{
int max = 0;
foreach (var value in this.Values)
{
if (value.Count > max)
max = value.Count;
}
foreach (var value in this.Values)
{
while (value.Count < max)
value.Add(null);
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
CustomersByTime Customers = new CustomersByTime(Repository.GetCustomerByDateCategory());
CustomerListView.DataSource = Customers;
CustomerListView.DataBind();
}
</script>
<html>
<head>
<style type="text/css">
td, th, table { border:solid 1px black; border-collapse:collapse;}
</style>
</head>
<body>
<asp:Repeater ID="CustomerListView" runat="server">
<HeaderTemplate><table cellpadding="2" cellspacing="2"></HeaderTemplate>
<ItemTemplate>
<asp:Repeater runat="server" visible="<%#Container.ItemIndex==0 %>"
DataSource="<%#((CustomersByTime)(CustomerListView.DataSource)).Contractors %>" >
<HeaderTemplate>
<tr>
<th>Times</th>
</HeaderTemplate>
<ItemTemplate>
<th><%#((Person)Container.DataItem).person_name %></th>
</ItemTemplate>
<FooterTemplate>
</tr>
</FooterTemplate>
</asp:Repeater>
<tr>
<td><%#((KeyValuePair<DateTime, List<Person>>)(Container.DataItem)).Key.ToShortTimeString() %></td>
<asp:Repeater ID="Repeater1" runat="server" DataSource="<%# ((KeyValuePair<DateTime, List<Person>>)(Container.DataItem)).Value %>">
<ItemTemplate>
<td align="left" style="width: 200px;">
<%#Container.DataItem == null ? "" : ((Person)(Container.DataItem)).person_name%>
</td>
</ItemTemplate>
</asp:Repeater>
</tr>
</ItemTemplate>
<FooterTemplate></table></FooterTemplate>
</asp:Repeater>
</body>
</html>
順便說一句,如果你正在構建一個全新的應用程序,並有一定的學習時間,我肯定建議尋找ASP.NET MVC,其中有一個不平凡的學習曲線,但使得很多事情更簡單...在partiuclar這種複雜的數據渲染。
我不太瞭解你的問題。你有你的數據嗎?你知道如何把它放在ListView中嗎?你的意思是放在哪裏?無論你想要ListView是什麼。 – Letterman 2009-10-17 03:03:56