如何编写自定义模板字段的DataControlField
问题描述:
我正在使用GridView
来显示其中一个数据列的类型为DateTimeOffset
的数据。为了在用户的时区显示日期&次,我将用户的时区首选项保存到他或她的配置文件(属性值键“TimezoneOffset”),并且在格式化日期&次时需要访问它。如何编写自定义模板字段的DataControlField
如果我是用模板列,然后我需要写:
<abbr class="datetimeoffset">
<%#
((DateTimeOffset)Eval("CreatedDate"))
.ToOffset(new TimeSpan(-((Int32)Profile.GetPropertyValue("TimezoneOffset"))
.ToRepresentativeInRange(-12, 24), 0, 0)).ToString("f") %>
</abbr>
这也太复杂,不能重复使用。
我试着给代码隐藏添加一个TimeSpan
属性(至少将它移出数据绑定表达式),但显然在<%# ... %>
内无法访问视图的代码隐藏属性。
因此,我认为我需要编写一个自定义DataControlField
来格式化用户时区中的日期&次。
我已经开始用:
public class DateTimeOffsetField : DataControlField
{
private TimeSpan userOffsetTimeSpan;
protected override DataControlField CreateField()
{
return new DateTimeOffsetField();
}
protected override void CopyProperties(DataControlField newField)
{
base.CopyProperties(newField);
((DateTimeOffsetField)newField).userOffsetTimeSpan = userOffsetTimeSpan;
}
public override bool Initialize(bool sortingEnabled, System.Web.UI.Control control)
{
bool ret = base.Initialize(sortingEnabled, control);
int timezoneOffset = ((Int32)HttpContext.Current.Profile.GetPropertyValue("TimezoneOffset")).ToRepresentativeInRange(-12, 24);
userOffsetTimeSpan = new TimeSpan(-timezoneOffset, 0, 0);
return ret;
}
}
但现在我卡住了。如何为每个单元格输出HTML <abbr class="datetimeoffset"><%# ((DateTimeOffset)Eval("CreatedDate")).ToOffset(userOffsetTimeSpan).ToString("f") %></abbr>
?
编辑:我一直在阅读一篇文章,标题为Cutting Edge: Custom Data Control Fields。到目前为止,我还补充说:
public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
{
base.InitializeCell(cell, cellType, rowState, rowIndex);
if (cellType == DataControlCellType.DataCell)
{
InitializeDataCell(cell, rowState, rowIndex);
}
}
protected virtual void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState, int rowIndex)
{
System.Web.UI.Control control = cell;
if (control != null && Visible)
{
control.DataBinding += new EventHandler(OnBindingField);
}
}
protected virtual void OnBindingField(object sender, EventArgs e)
{
var target = (System.Web.UI.Control)sender;
if (target is TableCell)
{
TableCell tc = (TableCell)target;
}
}
但而文章设置TableCell
实例的Text
财产,我想呈现的局部视图到表格单元格。那可能吗?
答
我想通了。以下是我结束了:
// DateTimeOffsetField.cs
public class DateTimeOffsetField : BoundField
{
private TimeSpan userOffsetTimeSpan;
protected override DataControlField CreateField()
{
return new DateTimeOffsetField();
}
protected override void CopyProperties(DataControlField newField)
{
base.CopyProperties(newField);
((DateTimeOffsetField)newField).userOffsetTimeSpan = userOffsetTimeSpan;
}
public override bool Initialize(bool sortingEnabled, System.Web.UI.Control control)
{
bool ret = base.Initialize(sortingEnabled, control);
int timezoneOffset = ((Int32)HttpContext.Current.Profile.GetPropertyValue("TimezoneOffset")).ToRepresentativeInRange(-12, 24);
userOffsetTimeSpan = new TimeSpan(-timezoneOffset, 0, 0);
return ret;
}
protected override void OnDataBindField(object sender, EventArgs e)
{
base.OnDataBindField(sender, e);
var target = (Control)sender;
if (target is TableCell)
{
var tc = (TableCell)target;
var dataItem = DataBinder.GetDataItem(target.NamingContainer);
var dateTimeOffset = (DateTimeOffset)DataBinder.GetPropertyValue(dataItem, DataField);
tc.Controls.Add(new TimeagoDateTimeOffset { DateTimeOffset = dateTimeOffset.ToOffset(userOffsetTimeSpan) });
}
}
}
TimeagoDateTimeOffset.cs
:
[DefaultProperty("DateTimeOffset")]
[ToolboxData("<{0}:TimeagoDateTimeOffset runat=server></{0}:TimeagoDateTimeOffset>")]
public class TimeagoDateTimeOffset : WebControl
{
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public DateTimeOffset DateTimeOffset
{
get { return (DateTimeOffset)ViewState["DateTimeOffset"]; }
set { ViewState["DateTimeOffset"] = value; }
}
protected override void RenderContents(HtmlTextWriter writer)
{
writer.BeginRender();
writer.AddAttribute(HtmlTextWriterAttribute.Class, "timeago", false);
writer.AddAttribute(HtmlTextWriterAttribute.Title, DateTimeOffset.ToString("o"));
writer.RenderBeginTag("abbr");
writer.Write(DateTimeOffset.ToString("d"));
writer.RenderEndTag();
writer.EndRender();
}
}