经常上CSDN社区论坛的朋友应该知道在CSDN里面结贴的时候会让你给各个回帖的人一定的分值作为报酬。此时我们不能固定TextBox框的个数,因为回帖的人数是不固定的。而且如果将TextBox控件和单一的回帖人关联则会导致后台代码冗余,也不利于维护和扩展吗,显得不灵活不显示。
QQ空间的留言本里面也是类似的情况。当有人给我们留言的时候我们要回复这个留言就点击“回复”就会出现一个TextBox框出来,然后我们填好自己的留言点击“提交”系统就自动提交了我们的留言。一般对这种重复的数据读取我们经常是用Repeater控件来做,而且也能比较灵活得分页,更可贵的是它能够做到动态生成控件。
下面我们就来实现类似QQ留言和回复留言的效果。
<asp:Repeater ID="Rep" runat="server">
<ItemTemplate>
<table border="1" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td id="Right_img" width="25%" align="center" valign="top" rowspan="3">
<br />
<%# "<img src=" + "../image/head/" + DataBinder.Eval(Container.DataItem,"HeadImage") + ".gif" + ">" %>
<br />
<br />
<br />
<%# DataBinder.Eval(Container.DataItem, "Name") %>
<br />
<%# DataBinder.Eval(Container.DataItem, "GuessDate") %>
</td>
<td id="Right_Top" height="22" align="center">
留言标题:<%# DataBinder.Eval(Container.DataItem, "Title") %>
</td>
</tr>
<tr>
<td valign="top" align="left" style="padding-top:15px;padding-bottom:25px;padding-left:2px;">
<br />
<%# DataBinder.Eval(Container.DataItem, "Content") %>
<br />
<br />
<%# DataBinder.Eval(Container.DataItem, "Reply") %>
<%# DataBinder.Eval(Container.DataItem, "RDate") %>
<br />
<div id='<%#"Reply" + DataBinder.Eval(Container.DataItem, "ID") %>' style="display:none;">
<p>----------------------------</p>
<asp:TextBox ID="RepInput" runat="server" TextMode="MultiLine" Width="300" Height="70"></asp:TextBox>
<br />
<asp:LinkButton ID="RepButton1" runat="server" CommandArgument= '<%# Eval("id")+","+(Container as RepeaterItem).ItemIndex%>' OnCommand="RepButton_Click" CommandName="save">提交</asp:LinkButton>
<a href="javascript:;" οnclick='HideReply("<%#"Reply"+DataBinder.Eval(Container.DataItem,"ID") %>")' >取消</a>
</div>
</td>
</tr>
<tr id="Right_Bottom" valign="middle">
<td height="22" valign="middle">
<div id="UserInfo">
<img class="im" src="../image/email.gif" alt="Email" height="15" width="15" /><%#"<a href=mailto:"+ DataBinder.Eval(Container.DataItem, "Email") +">电子邮箱</a> "%>
<img class="im" src="../image/home.gif" alt="Email" height="15" width="15" /><%#"<a href=http://"+ DataBinder.Eval(Container.DataItem, "HomePage")+" >个人主页</a>"%>
<img class="im" src="../image/oicq.gif" alt="Email" height="15" width="15" /><%#"<a href= "+ DataBinder.Eval(Container.DataItem, "QQ")+" >QQ</a> "%>
<span id="Master">
<a href="javascript:;" οnclick='ShowReply("<%#"Reply"+DataBinder.Eval(Container.DataItem,"ID") %>")'>回复留言</a>
<asp:LinkButton ID="LinkButton2" runat="server" OnClientClick="return confirm('确定要删除这条留言么?');" OnCommand="Del_Click" CommandArgument= '<%# DataBinder.Eval(Container.DataItem,"ID") %>'>删除留言</asp:LinkButton>
</span>
</div>
</td>
</tr>
</table>
</ItemTemplate>
</asp:Repeater>
我们姑且不去深究这段代码,只需要去注意一下红色部分就好。
红色部分是一个隐藏的Div层,里面是一个TextBox控件和一个用于提交回复留言的LinkButton控件。
本来这个层是隐藏的,正常情况下是看不到的。当我们点击下面的超链接“回复留言”的时候这个层就显示出来(相关的js代码忽略)。然后我们在这个层里的TextBox框输入我们的留言,随即点击“提交”控件提交内容。这个时候就有一个问题了:我们是怎么获得Repeater控件里面的控件值的(注意:这个控件是“活的”,是在运行的时候根据客户来输入的,而不是我们定死的内容,如Label控件!)并将这个值写进数据库中相关的表中并且用于区分是对这个留言者的回复?
要解决以上问题就必须了解Repeater控件的运行机制原理。既然是重复得读取记录,那么肯定有用于区分记录的“项值”,因此(Container as RepeaterItem).ItemIndex这个就是因此诞生。对于第一条记录它的只为0,第二条它的值为1,以此类推…因此我们就可以用它和我们数据库表中的主键一起传递到后台代码中。
CommandArgument= '<%# Eval("id")+","+(Container as RepeaterItem).ItemIndex%>'的意思很明显,id 就是后台数据库中留言记录唯一的主键值,中间隔一个逗号之后再连接一个项值。这样在后台我们就能够轻松得到这两个主要的值了。
后代相关事件代码如下:
public void RepButton_Click(object sender, CommandEventArgs e)
{
RepText = this.Rep.Items[Convert.ToInt32(e.CommandArgument.ToString().Split(',')[1])].FindControl("RepInput") as TextBox;
System.Data.OleDb.OleDbConnection con = MengXin.MyCode.DB.CreateConnect();
System.Data.OleDb.OleDbDataAdapter Ada = new System.Data.OleDb.OleDbDataAdapter("Select * from GuestBook where state = yes and ID = " + e.CommandArgument.ToString().Split(',')[0], con);
System.Data.OleDb.OleDbCommandBuilder Bui = new System.Data.OleDb.OleDbCommandBuilder( Ada );
DataSet ds = new DataSet();
Ada.Fill(ds, "RepGuestBook");
if (ds.Tables["RepGuestBook"].Rows.Count > 0)
{
ds.Tables["RepGuestBook"].Rows[0]["Reply"] = "----------------------<br />管理员回复:<br /><br /><p style='color:#fcb202'>" + RepText.Text + "</p><br />于";
ds.Tables["RepGuestBook"].Rows[0]["RDate"] = System.DateTime.Now.ToString();
Ada.Update(ds, "RepGuestBook");
}
else
{
Response.Write("<script language=javascript>alert('无记录!');window.location='Default.aspx';</script>");
}
con.Close();
Response.Write("<script language=javascript>window.location='Default.aspx';</script>");
}
注意事件中红色的部分,RepText是一个TextBox控件,主要是接收客户点击的项中的回复留言的内容。
具体的还需要多多练习实践。如果结合Ajax,实现一下局部刷新就完美实现了QQ留言板的功能了…
PS:以上代码在XP+IIS5.1+VS2008+IE8+ACCESS测试通过…