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

发布于 2024-10-14 04:43:30 字数 2873 浏览 2 评论 0原文

我正在使用 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 来格式化日期和日期。用户所在时区的时间。

我一开始就说:

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 <%# ((DateTimeOffset)Eval("CreatedDate")).ToOffset(userOffsetTimeSpan).ToString("f") %>< ;/abbr> 每个单元格?

编辑:我一直在阅读一篇标题为前沿的文章:自定义数据控制字段。到目前为止,我已经添加了:

    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 属性,但我想将部分视图渲染到表格单元格中。这可能吗?

I am using a GridView to display data where one of the data columns has type DateTimeOffset. In order to display dates & times in the user's timezone, I save the user's timezone preference to his or her profile (property value key "TimezoneOffset"), and need to access it when formatting dates & times.

If I were to use templatefield, then I would need to write:

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

which is too complicated and not reusable.

I tried adding a TimeSpan property to the code-behind (to at least move that out of the data binding expression), but apparently properties of the view's code-behind are inaccessible within <%# ... %>.

Therefore, I think that I need to write a custom DataControlField to format dates & times in the user's timezone.

I have started with:

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

But now I am stuck. How do I output the HTML <abbr class="datetimeoffset"><%# ((DateTimeOffset)Eval("CreatedDate")).ToOffset(userOffsetTimeSpan).ToString("f") %></abbr> for each cell?

EDIT: I have been reading an article titled Cutting Edge: Custom Data Control Fields. So far I have added:

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

but whereas the article sets the Text property of the TableCell instance, I would like to render a partial view into the table cell. Is that possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蛮可爱 2024-10-21 04:43:30

我想通了。这是我最终得到的结果:

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

I figured it out. Here is what I ended up with:

// 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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文