【问题标题】:How to set the RowStyle of a GridView row depending on a property of the Object that the row is being bound to如何根据行绑定到的对象的属性设置 GridView 行的 RowStyle
【发布时间】:2010-01-20 15:12:39
【问题描述】:

我目前正在使用 GridView,我想根据行绑定到的对象的属性为行设置 CssClass。

我尝试了以下方法,但它不起作用(请参阅 cmets):

<asp:GridView id="searchResultsGrid" runat="server" AllowPaging="true" PageSize="20" AutoGenerateColumns="false">

<!-- The following line doesn't work because apparently "Code blocks 
aren't allowed in this context: -->
  <RowStyle CssClass="<%#IIF(DataBinder.Eval(Container.DataItem,"NeedsAttention","red","") %>

  <Columns>
<!--............-->
  </Columns>
</asp:GridView>

现在我可以简单地处理 GridView 的 RowDataBound 事件并更改那里的行的 css 类...但我试图在 UI 和页面/业务逻辑层之间保持清晰的分离。

我不知道如何做到这一点,我期待听到任何建议。

谢谢,

-弗林尼

【问题讨论】:

    标签: asp.net gridview


    【解决方案1】:

    您不能在声明性标记中执行此操作。

    几乎所有GridView 的声明性属性(包括GridView.RowStyle)都是网格级设置而不是行级设置。除了 TemplateFields 之外,它们不是绑定的数据容器,因此它们无法访问其行中的数据。

    如果您想将此逻辑保留在 .aspx 模板中,您唯一真正的选择是使用模板字段并操作其内容:

    <asp:TemplateField>
        <ItemTemplate>
            <span class="<%# ((string)Eval("property3")) == "NeedsAttention" ? "red" : string.Empty %>">
                <%# Eval("property1") %>
            </span>
        </ItemTemplate>                        
    </asp:TemplateField>
    

    根据您要执行的操作,这可能会很尴尬 - 您无权访问包含的 &lt;td&gt;(或 &lt;tr&gt;),您必须为每个单元格重复格式化。

    GridView 类竭尽全力向您隐藏 HTML 和样式的细节。毕竟您可以创建一个GridView control adapter,它甚至不会呈现为HTML 表格。 (虽然不太可能。)

    因此,即使您试图避免它,您最好还是在 OnRowDataBound 处理程序中处理此问题 - 或使用 Repeater(如果合适的话)。

    【讨论】:

    • 是的,我也想过这个问题,但我不满意我必须为行中的每个 TemplateField 和 BoundField 执行此操作。这会很尴尬。也许我会硬着头皮处理 OnRowBound 事件。这么多让我的图层分开。
    • 谢谢杰夫。尽管这个答案令人失望,但至少你已经确认这是不可能的。
    • 你打赌 - 我很抱歉带来坏消息。 GridView 就是它的样子,并带来了许多失望;我尽量避免它。当它的优势(例如它们)无法抗拒时,我也只是硬着头皮。
    【解决方案2】:

    我知道已经快一年了,但是如果其他人正在尝试这个,请尝试将 GridView 子类化。

    public class GridViewCSSRowBindable : GridView
    {
      public string DataFieldRowCSSClass { get; set; }
      protected override void OnRowDataBound(GridViewRowEventArgs e)
      {
        base.OnRowDataBound(e);
        if (!string.IsNullOrEmpty(DataFieldRowCSSClass))
        {
          //This will throw an exception if the property does not exist on the data item:
          string cssClassString = DataBinder.Eval(e.Row.DataItem, DataFieldRowCSSClass) as string;
          if (!string.IsNullOrEmpty(cssClassString))
          {
            string sep = string.IsNullOrEmpty(e.Row.CssClass) ? string.Empty : " ";
            e.Row.CssClass += sep + cssClassString;
          }
        }
      }
    }
    

    然后在您的页面中:

    <custom:GridViewCSSRowBindable ID="gvExample" runat="server" DataFieldRowCSSClass="RowCSS">
    </custom:GridViewCSSRowBindable>
    

    绑定到此示例 GridView 的对象应具有公共字符串 RowCSS 属性。

    如果您之前没有使用过继承控件,您可能需要查看如何在您的项目中进行设置。

    【讨论】:

    • 因为 GridView.RowDataBound 是公共事件,您可以在事件处理程序中执行与此类似的操作。如果由于某种原因不能子类化 GridView,使用事件处理程序可能会很有用。
    • 我什至不记得发布过这个问题!但是,关键是我不想在控制风格后面有代码。我想将我的 UI 内容保留在 ASP 代码中,从而避免使用 OnRowDataBound 事件。因此,虽然您的解决方案可行,但我一直在寻找另一种方法来做到这一点(不使用后面的代码)。不过感谢您的回复。这对那些不知道 OnRowBound 事件的人很有帮助。
    • @Frinavale 您可以将事件处理程序放在 aspx/ascx 中的 &lt;script runat="server"&gt; 块中
    【解决方案3】:
    foreach (TableCell gvc in gvRowPhistry.Cells)
    {
        gvc.ForeColor = System.Drawing.Color.Blue;
    }
    

    【讨论】:

    • 多一点解释可能有助于其他程序员理解代码是如何工作的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多