如何编写类似自定义模板字段的DataControlField

时间:2011-01-22 16:30:02

标签: c# asp.net data-binding templatefield

我使用GridView来显示其中一个数据列的类型为DateTimeOffset的数据。为了显示日期和在用户的时区中,我将用户的时区偏好保存到他或她的个人资料(属性值键“TimezoneOffset”),并且需要在格式化日期和时间时访问它。次。

如果我使用templatefield,那么我需要写:

<abbr class="datetimeoffset">
<%#
    ((DateTimeOffset)Eval("CreatedDate"))
    .ToOffset(new TimeSpan(-((Int32)Profile.GetPropertyValue("TimezoneOffset"))
                            .ToRepresentativeInRange(-12, 24), 0, 0)).ToString("f") %>
</abbr>

这太复杂而且不可重复使用。

我尝试在代码隐藏中添加TimeSpan属性(至少将其移出数据绑定表达式),但显然在<%# ... %>内无法访问视图代码隐藏的属性。

因此,我认为我需要编写自定义DataControlField来格式化日期&amp;在用户的时区中的时间。

我已经开始:

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;
        }
    }

但是文章设置Text实例的TableCell属性,我想在表格单元格中呈现局部视图。这可能吗?

1 个答案:

答案 0 :(得分:1)

我明白了。以下是我最终的结果:

// 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();
    }
}