4

我正在阅读 ASP.NET 4.5 Web 窗体功能以了解新功能。我最近使用 GridView尝试了强类型数据控件功能。但是,据我所知,您只能在使用asp:TemplateField ..... 时使用强类型的好处,如下所示:

            <asp:TemplateField HeaderText="Name" >
                <ItemTemplate>
                    <%# Item.Name.ToString() %>
                </ItemTemplate>
            </asp:TemplateField>

这是真的吗?您不能在 GridView 中对 asp:BoundField、asp:DynamicField 或任何其他可能的列控件使用强类型?
例如,当我放置一个标准的 asp:BoundField 时,它没有为我提供任何智能感知自动完成功能。我只能为 DataField 属性输入一个字符串。像这样:

<asp:BoundField DataField="JyooobTitle" HeaderText="Job Title" />

哎呀!看起来我在那里拼错了“JobTitle”,但编译器没有抓住它。因此,为了从强类型中受益,我似乎被迫使用 TemplateField 选项....对于每一列,无论我是否需要它!

此外,如果你想在你的 TemplateField 上放置一个 SortExpression 属性......你必须希望你也能正确地拼写那个,因为看起来你也没有得到强类型。希望我只是遗漏了一些明显的东西,因为这是一个很棒的新功能,但它肯定看起来只是实现了一半

任何人都可以验证这是否属实......或者我是否遗漏了什么?

4

2 回答 2

1

作为一个相对较新的 ASP.NET 开发人员,我可能没有洞察力或经验来知道这个问题的完整答案,但我会尽我所能理解这个问题。我也使用过 ASP.net 4.5“强类型模型绑定”。当我第一次通过 Scott Hanselman 的精彩视频发现它时,它让我大吃一惊。您提到的问题绝对是该功能的不幸限制。但是,我认为我们应该感谢我们得到的帮助。

考虑您在.aspx页面中的其他工作。虽然 Intellisense 确实提供了一些填充控件属性的帮助(例如,true/false 下拉列表Visible=),但总体而言,声明性标记的验证非常少。这是它非常自然的一部分。它不是“编程”文档,而是语义文档。由于这个事实,它可以在不重新编译项目的情况下进行更改,这有时非常方便。

ASP.NET 确实提供了一种通过内联代码段(<%# %> 等)将实际编译代码放置在 aspx 标记中的方法。强类型绑定利用了这些。它们就像进入编程世界的后门,为您提供完整的 Intellisense 体验。

我希望有一天我们可能会在DataField属性中看到强类型,但我不会过早地寻找它。现在,我将ItemType随时利用它的便利并为之欢欣鼓舞。

于 2013-02-07T02:38:30.637 回答
0

这是我解决排序表达式绑定问题的方法。

我没有设置SortExpression为真实的属性名称,而是将其设置为列的序号位置。

<Columns>
    <asp:TemplateField HeaderText="Name" SortExpression="1" >
        <ItemTemplate>
            <%# Item.Name %>
        </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField HeaderText="Job Title" SortExpression="2" >
        <ItemTemplate>
            <%# Item.JobTitle %>
        </ItemTemplate>
    </asp:TemplateField>
</Columns>

然后,将处理程序附加到 gridview 的Sorting事件。

<asp:GridView runat="server"
              OnSorting="Sorting"
              ...

事件参数之一是您之前定义的排序表达式(即"1"or "2")。您可以使用此值以编程方式将排序表达式重新绑定到实际属性名称。

注意:遵循这种方法意味着放弃升序/降序排序之间的自动切换。不过,重新实现它并不是特别困难。

注意:我使用基于反射的方法在执行时确定属性名称。

protected void Sorting(object sender, GridViewSortEventArgs e)
{
    int columnPosition;
    if (!int.TryParse(e.SortExpression, out columnPosition))
    {
        return;
    }

    switch (columnPosition)
    {
        case 1:
            e.SortExpression = Reflector.GetPropertyName<Employee>(o => o.Name);
            break;

        case 2:
            e.SortExpression = Reflector.GetPropertyName<Employee>(o => o.JobTitle);
            break;
    }

    var grid = (GridView)sender;
    if (grid.SortExpression == e.SortExpression)
    {
        if (grid.SortDirection == SortDirection.Ascending)
        {
            e.SortDirection = SortDirection.Descending;
        }
    }
}

最后,这是我Reflector在上面示例中使用的类的代码。

/// <summary>Utility class. Provides static reflection-based utility methods.</summary>
public static class Reflector
{
    #region Public Methods and Operators

    /// <summary>Gets the name of the property that is accessed by the given expression. Usage: <c>Reflector.GetPropertyName&lt;MyClass&gt;(obj =&gt; obj.MyProperty);</c></summary>
    /// <param name="selectorExpression">The expression that selects the property of which the name should be returned.</param>
    /// <typeparam name="T">The type that defines the property.</typeparam>
    /// <returns>The name of the property.</returns>
    public static string GetPropertyName<T>(Expression<Func<T, object>> selectorExpression) where T : class
    {
        MemberExpression memberExpression;
        var unaryExpression = selectorExpression.Body as UnaryExpression;
        if (unaryExpression != null)
        {
            memberExpression = unaryExpression.Operand as MemberExpression;
        }
        else
        {
            memberExpression = selectorExpression.Body as MemberExpression;
        }

        if (memberExpression == null)
        {
            return null;
        }

        return memberExpression.Member.Name;
    }

    #endregion
}
于 2014-10-15T09:20:23.123 回答