第一步的目的就是先写一个简单的首页,里面只有一个论坛分组的列表,论坛以CSDN的为例,取了前三个大分类模拟记录。1.建表我喜欢用Ecxel写文档数据库说明,比较方便,还有很多偷懒的技巧。表名是bbs_board
结构如下: 
1  BoardID        int 自增 主键    
2  BoardName      nvarchar 100 论坛分组名称    
3  BoardLevel     int 论坛分组类型。1:大分类;2:小分类    
4  ParentID       int 0 父ID。上级节点的ID    
5  ChildCount     int 0 子栏目数量    
6  OrderID        int 0 排序用    
7  TopicNum       int 0 主题数    
8  PostNum        int 0 回复数    
9  todayNum       int 0 今日主题数    
10 AddedDate      datetime getDate() 添加时间    
11 BoardMasterID  nvarchar 200 版主ID(会员ID)    
12 BoardMaster    nvarchar 1000 版主    
13 Readme         nvarchar 1000 论坛分组的介绍    
14 LastPost nvarchar 1000 最后发帖情况  分组采用无级分组的设计,但是实际上只有两极——大分类和小分类。2.填入模拟数据我用了CSDN的几个分类作为模拟记录3.编写.asp.cs文件既然是二级分组,那么就涉及到了控件嵌套的问题,最简便的方法呢就是外面用DataList,里面用DataGrid。
灵活的方法呢就是用Repeater套Repeater,这样呢既节省了资源,又能够满足各种复杂页面的要求。下面先说一下简便的方法:A.利用数据层取得记录集
Jyk.DAL add = new Jyk.DAL();
DataView dv = add.runSqlDataSet("select * from bbs_board").Tables[0].DefaultView;
这里建立了一个DataView 对象来存储记录。B.绑定DataList
dv.RowFilter = "ParentID = 0";
DL1.DataSource=dv;
DL1.DataBind();利用RowFilter属性来取得大分类的记录
下面就是绑定代码了add.Dispose();C.绑定DataList里面的DataGrid
DataGrid tmpDG = new  DataGrid();
foreach (DataListItem item in DL1.Items )
{
dv.RowFilter = "ParentID = " + DL1.DataKeys[item.ItemIndex].ToString();
tmpDG = (DataGrid)item.FindControl("DG");
tmpDG.DataSource=dv;
tmpDG.DataBind();
}
常见的思路呢是在DataList的ItemDataBound事件里面绑定,我觉得那么写效率不好,所以我采用遍历的方法来实现。
先定义一个临时的DataGrid对象,用来存放DataList里面的DataGrid,然后遍历DataList,取得每一行的DataGrid,最后就是绑定。
当然了要先设置DL1 的 DataKeys 属性(DL1.DataKeys="BoardID";),用它来存放大分类的ID,然后在遍历里面用
DL1.DataKeys[item.ItemIndex].ToString();
来取出大分类的ID,用于去度对应的小分类。D.释放资源
add.Dispose();最后释放资源。
Repeater的方法基本上是一样的,换一下对象名就行了。我就不详细说明了Jyk.DAL add = new Jyk.DAL();
DataView dv = add.runSqlDataSet("select * from bbs_board").Tables[0].DefaultView;dv.RowFilter = "ParentID = 0";
Rpt1.DataSource=dv;
Rpt1.DataBind();

Repeater tmpRpt = new Repeater();
foreach (RepeaterItem item in Rpt1.Items )
{
tmpRpt = (Repeater)item.FindControl("Rpt2");
dv.RowFilter = "ParentID = " + tmpRpt.DataMember ;
tmpRpt.DataSource=dv;
tmpRpt.DataBind();
}
add.Dispose();对了,有一点要说明一下。Repeater没有DataKeys属性,但是我们可以用DataMember来代替。这个是写在里层的Repeater的。还有一个要说明的,如果按照三层结构的思路呢,应该建立一个.cs文件,然后把取得记录集的两行语句放进去。
我觉得这么写很是麻烦,分出去写还是两行代码没有减少,而且还要多一个.cs文件,等等,好像三层结构是不可以返回一个杂乱无章的记录集的,要分开写,返回大分类的记录集绑定外边的控件;再返回第一个大分类的小分类的记录集来绑定里面的第一个控件,然后是第二个,第三个......
我对三层结构理解的不深,不知道是不是这个意思。
4.描绘.aspx页面这个是很重要的了,给人的第一感觉是由页面来决定的,这就要烦劳美工来帮忙了,我是不行的,我只会把美工写好的html代码拿来用现成的。现在呢没人帮忙,只好写“素面”了,就是没有美化的页面。A.DataList——DataGrid法
<asp:datalist id="DL1" runat="server" DataKeyField="BoardID">
<ItemTemplate>
<asp:Label id=Lbl_title runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.BoardName") %>'></asp:Label>
<br>
<asp:datagrid id="DG" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundColumn DataField="BoardName" HeaderText="讨论区"></asp:BoundColumn>
<asp:BoundColumn DataField="TopicNum" HeaderText="主题数"></asp:BoundColumn>
<asp:BoundColumn DataField="PostNum" HeaderText="帖子数"></asp:BoundColumn>
<asp:BoundColumn DataField="LastPost" HeaderText="最后发表"></asp:BoundColumn>
<asp:BoundColumn DataField="BoardMaster" HeaderText="版主"></asp:BoundColumn>
</Columns>
</asp:datagrid>
</ItemTemplate>
</asp:datalist>
B.Repeater——Repeater法
<asp:Repeater id="Rpt1" runat="server">
<HeaderTemplate>
<table border="0" width="500" cellspacing="0" rules="all">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td colspan="5">
<%# DataBinder.Eval(Container, "DataItem.BoardName") %>
</td>
</tr>
<!--放里面的Repeater。为了能清楚一点,写在了下面。用的时候要把下面的代码考进来。-->
</ItemTemplate>
<FooterTemplate>
</TABLE>
</FooterTemplate>
</asp:Repeater>//里面的Repeater
<asp:Repeater id="Rpt2" runat="server" DataMember='<%# DataBinder.Eval(Container, "DataItem.BoardID") %>'>
<HeaderTemplate>
<tr>
<td>讨论区</td>
<td>主题数</td>
<td>帖子数</td>
<td>最后发表</td>
<td>版主</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# DataBinder.Eval(Container, "DataItem.BoardName") %>&nbsp;
</td>
<td><%# DataBinder.Eval(Container, "DataItem.TopicNum") %>&nbsp;
</td>
<td><%# DataBinder.Eval(Container, "DataItem.PostNum") %>&nbsp;
</td>
<td><%# DataBinder.Eval(Container, "DataItem.LastPost") %>&nbsp;
</td>
<td><%# DataBinder.Eval(Container, "DataItem.BoardMaster") %>&nbsp;
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
<asp:Repeater id="Rpt2" runat="server" DataMember='<%# DataBinder.Eval(Container, "DataItem.BoardID") %>'>
这是里面的Repeater,注意 DataMember 的写法。

解决方案 »

  1.   

    http://www.jyklzz.net/bbs/index.aspx
    这是演示页面,没有美化,所以呢很是难看了,建议看之前先做好心理准备:)
      

  2.   

    我想你这些文章应该放到blog里面去给大家看
    一般上论坛的人都是问问题的都比较匆忙,没有时间看
      

  3.   

    呵呵,支持!不过还是建议放在你的 blog 里面去!正如楼上所说,这里大多数是来问问题的,没有太多的时间来欣赏你的大作!
      

  4.   

    blog怎么用呀?不会用,谁能教教我? 版主ID 和版主字段都是 nvarchar  的,而不是int的,多个版主就连成字符串好了,好像叫做序列化吧。
      

  5.   

    有一样一段代码:
    <asp:repeater runat="server" > //主Repeater
    <ItemTemplte>
    <table><tr><td>主题号<a><%# DataBinder.Eval(Container, "DataItem.TopicID") %></a></td>
    <td>主题名:<a><%# DataBinder.Eval(Container, "DataItem.TopicName") %></a></td>
    <td>最后回复时间:<a><%# DataBinder.Eval(Container, "DataItem.LastPost") %></a></td>
    ..........
    .........
    </tr></table>
    <asp:repeater runat DataSoure='<% GetAllApplyAboutThisTopic(DataBinder.Eval (Container, "DataItem.TopicID") )%>'>   //GetAllApplayAboutThisTipic为后台代码中一函数,                                      //返回一数据绑定源,如dataset,datatable,dataview
                        //其中传了一参数(TopicID:主题号)以得到关于某一                   //主题的所有回复。。<itemItemplate>
    关于此主题的回复:
    回复号:<%# DataBinder.Eval(Container, "DataItem.ReplyID") %><br>
    回复人:<%# DataBinder.Eval(Container, "DataItem.ReplyUser") %><br>
    回复内容:<%# DataBinder.Eval(Container, "DataItem.ReplyContent") %><br>
      </ItemTemplate</itemItemplate>
    </repeater>
    类似于这样。可以在repeater 中嵌套repeater(可以形成多重嵌套,如3层repeater,4层repeater嵌套)
    我在这样提出。最好用repeater,因为repeater数据绑定在页面层带来的开销是最小的。(比datalisgt,datagrid都要小)
      

  6.   

    我写了一个DataList  嵌套 DataGrid 和 一个Repeater 嵌套 Repeter 两个方法,我是想说一下嵌套的种类方法有很多,各有各的优点、缺点。在论坛里使用repeater 中嵌套repeater是比较理想的方法,节省资源,又可以应付美工做出来的各式各样的html代码,只是写起来有一点点麻烦。写两个也是一种对比,可以发现一些异同点。便于学习探讨。
      

  7.   

    Jyk.DAL add = new Jyk.DAL(); 什么意思啊?
      

  8.   

    Jyk.DAL add = new Jyk.DAL();
    这是数据层
    DataView dv = add.runSqlDataSet("select * from bbs_board").Tables[0].DefaultView;
    这是数据层的一个方法,传入查询语句,返回DataSet.