积极答复者
我该创建用户控件还是自定义控件?回发后数据丢失?

问题
-
我想要创建一个控件,可以如下使用:
<uc:RatingLabel Rating="5" runat="server" />
这样就在页面上显示5个星星。
之所以想这样,是因为我可以在数据控件——如DetailsView——里使用,如下
<uc:RatingLabel Rating='<%# Eval("rating") %>' runat="server" />
这样无需后台代码,就能显示个性化的数据了。我目前是用用户控件来做的,代码如下:
<%@ Control Language="C#" ClassName="RatingLabel" %> <script runat="server"> private float rating; private int height = 24; public decimal Rating { get { return (decimal) rating; } set { if (value < 0) throw new ArgumentOutOfRangeException("rating不可为负数"); rating = (float) value; label.Attributes["title"] = "Rating " + rating; label.Controls.Clear(); int roundedValue = (int)Math.Round(rating, 0, MidpointRounding.AwayFromZero); for (int i = 0; i < roundedValue; i++) { HtmlGenericControl img = new HtmlGenericControl(); img.TagName = "img"; img.Attributes["src"] = ResolveClientUrl("~/Images/star.jpg"); img.Attributes["alt"] = "Star"; img.Attributes["height"] = height.ToString(); label.Controls.Add(img); } } } public int Height { get { return height; } set { height = value; } } </script> <span id="label" runat="server"/>
这段代码的问题是,当它用在DetailsView的模板里,页面回发后星星就消失了。
请问面对这种需求,我应该创建用户控件还是自定义控件?为什么?
为什么用在DetailsView的模板里,页面回发后星星消失?怎么避免这个问题?
- 已编辑 爱让一切都对了 2012年3月17日 3:38
答案
-
我觉得这不是一个好办法。因为asp.net自带的控件如button、label用于数据控件模板里都没有问题,不需要你所谓的Click按钮事件当中再次绑定。
当然不是好办法,但是你的控件只能这样做了。
还有一个办法,就是你我的代码从IsPostBack中移出来,这样每次回发都自动绑定。
建议你用AJAX 的Rating控件最好。
- 已标记为答案 Song TianModerator 2012年3月23日 9:17
全部回复
-
原因在于你用UserControl的话没有实现数据绑定接口,导致回传时候无法再次获得数据源。
两个办法:
1)Click按钮事件当中再次绑定:
public partial class UserStar : System.Web.UI.UserControl { private double rating = 0.0f; /// <summary> /// 绑定Rating /// </summary> [Bindable(true)] public double Rating { get { return rating; } set { if (value < 0) throw new ArgumentOutOfRangeException("rating不可为负数"); else { rating = value; } } } protected override void Render(HtmlTextWriter writer) { int roundedValue = (int)Math.Round(rating, 0, MidpointRounding.AwayFromZero); for (int i = 0; i < roundedValue; i++) { Response.Write("★"); } } }
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CSharp.Default" %> <%@ Register Src="UserStar.ascx" TagName="UserStar" TagPrefix="uc1" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:Repeater ID="Repeater1" runat="server"> <HeaderTemplate> <table> </HeaderTemplate> <ItemTemplate> <tr> <td> <uc1:UserStar ID="UserStar1" runat="server" Rating='<%#Eval("Num") %>' /> </td> </tr> </ItemTemplate> <FooterTemplate> </table> </FooterTemplate> </asp:Repeater> </div> </form> </body> </html>
namespace CSharp { public partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { Repeater1.DataSource = new[] { new{Num=1.0}, new{Num=5.0} }; Repeater1.DataBind(); } } protected void Button1_Click(object sender, EventArgs e) { Repeater1.DataSource = new[] { new{Num=1.0}, new{Num=5.0} }; Repeater1.DataBind(); } } }
2)或者直接使用Rating的AJAX控件(注意不要忘记放上ScriptManager)。
http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/Rating/Rating.aspx(设置CurrentRrating作为绑定属性)。
- 已编辑 ThankfulHeart 2012年3月17日 5:37
-
我觉得这不是一个好办法。因为asp.net自带的控件如button、label用于数据控件模板里都没有问题,不需要你所谓的Click按钮事件当中再次绑定。
当然不是好办法,但是你的控件只能这样做了。
还有一个办法,就是你我的代码从IsPostBack中移出来,这样每次回发都自动绑定。
建议你用AJAX 的Rating控件最好。
- 已标记为答案 Song TianModerator 2012年3月23日 9:17