我已經實現了一個簡單的控件,該控件呈現abbr
標籤以便使用jQuery TimeAgo插件。自定義BoundField失去對回傳的控制
public class TimeAgoControl : System.Web.UI.WebControls.WebControl
{
[Bindable(true)]
[DefaultValue(null)]
public string Iso8601Timestamp
{
get { return (string)ViewState["Iso8601Timestamp"]; }
set { ViewState["Iso8601Timestamp"] = value; }
}
[Bindable(true)]
[DefaultValue(null)]
public override string ToolTip
{
get { return (string)ViewState["ToolTip"]; }
set { ViewState["ToolTip"] = value; }
}
public override void RenderControl(HtmlTextWriter writer)
{
writer.AddAttribute("class", "timeago");
writer.AddAttribute("title", Iso8601Timestamp);
writer.RenderBeginTag("abbr");
RenderContents(writer);
writer.RenderEndTag();
}
protected override void RenderContents(HtmlTextWriter writer)
{
writer.WriteEncodedText(ToolTip);
}
}
這工作正常。我可以用上面的控制在GridView TemplateField
,並且也能正常工作:
<asp:TemplateField>
<ItemTemplate>
<my:TimeAgoControl runat="server" Iso8601Timestamp='<%# Item.LastImportDate.ToString("s") %>'
ToolTip='<%# Item.LastImportDate.ToString("f") %>' />
</ItemTemplate>
</asp:TemplateField>
當然,我寧願沒有輸入所有的我想用控制在GridView每次上面,所以我我認爲我會將上述邏輯抽象爲自定義BoundField
,我只需傳遞包含要渲染的DateTime
值的DataField
的名稱即可。很簡單,從System.Web.UI.WebControls.BoundField
延伸並覆蓋InitializeDataCell
方法,將控件添加到其中的DataControlFieldCell
,並將處理程序附加到DataBinding
事件。它的工作原理,併產生正確的標記:
<td><abbr class="timeago" title="Wednesday, January 29, 2014 16:17">about 23 hours ago</abbr></td>
但是,當頁面做了回發,控制消失了,所有我留下的是
<td>29.01.2014 16:17:17</td>
請注意,的頁面不使用Ajax功能:它不包含UpdatePanel和ScriptManagers。
我已經研究了不少,發現this懸而未決的問題以及本other問題,其中指出,一個必須重寫ExtractValuesFromCell
方法,這在我的情況下不會被調用。下面是我實現
public class TimeAgoBoundField : System.Web.UI.WebControls.BoundField
{
protected override void InitializeDataCell(System.Web.UI.WebControls.DataControlFieldCell cell, System.Web.UI.WebControls.DataControlRowState rowState)
{
base.InitializeDataCell(cell, rowState);
cell.Controls.Add(new TimeAgoControl());
cell.DataBinding += (sender, e) =>
{
var c = (DataControlFieldCell)sender;
//how do I get the TimeAgoControl within this scope? c.Controls.Count is 0
var dateTimeValue = (DateTime?)DataBinder.GetPropertyValue(DataBinder.GetDataItem(c.NamingContainer), this.DataField);
c.Controls.Add(new TimeAgoControl
{
Iso8601Timestamp = dateTimeValue.HasValue ? dateTimeValue.Value.ToLocalTime().ToString("s") : this.NullDisplayText,
ToolTip = DateTimeValue.HasValue ? dateTimeValue.Value.ToLocalTime().ToString("f") : this.NullDisplayText
});
};
}
}
需要注意的是,如果我添加控件不在DataBind
事件處理程序,而是在InitializeDataCell
本身的建議here,該Controls
收集空(作爲一個後果,給控件的ID和嘗試使用FindControl
失敗,返回null)。很顯然,DataBind
事件不會在回發中調用,但是鑑於ViewState
在生命週期的這個階段處於活動狀態,我會希望控件在回發時保持不變。
任何指針將不勝感激。提前致謝。