【问题标题】:Conditionally hide CommandField or ButtonField in Gridview有条件地在 Gridview 中隐藏 CommandField 或 ButtonField
【发布时间】:2010-11-30 11:37:28
【问题描述】:

我有一个 GridView 显示人员记录。我想根据基础记录的某些属性有条件地显示CommandFieldButtonField。这个想法是只允许对特定的人执行命令。

最好的方法是什么?我更喜欢声明性解决方案而不是程序性解决方案。

【问题讨论】:

  • 您能否详细说明您所说的声明性解决方案是什么意思?
  • @RussCam 我认为他的意思是“尽可能少的 C#”,使用标记语法而不是代码隐藏。

标签: asp.net gridview


【解决方案1】:

可以在RowDataBound 事件触发时完成

  protected void GridView_RowDataBound(Object sender, GridViewRowEventArgs e)
  {
    if(e.Row.RowType == DataControlRowType.DataRow)
    {
      // Hide the edit button when some condition is true
      // for example, the row contains a certain property
      if (someCondition) 
      {
          Button btnEdit = (Button)e.Row.FindControl("btnEdit");

          btnEdit.Visible = false;
      }
    }   
  }

这是一个演示页面

标记

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="DropDownDemo._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>GridView OnRowDataBound Example</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">
            <Columns>
                <asp:BoundField HeaderText="Name" DataField="name" />
                <asp:BoundField HeaderText="Age" DataField="age" />
                <asp:TemplateField>
                    <ItemTemplate>                
                        <asp:Button ID="BtnEdit" runat="server" Text="Edit" />
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </form>
</body>
</html>

代码背后

using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;

namespace GridViewDemo
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            GridView1.DataSource = GetCustomers();
            GridView1.DataBind();
        }

        protected override void OnInit(EventArgs e)
        {
            GridView1.RowDataBound += new GridViewRowEventHandler(GridView1_RowDataBound);
            base.OnInit(e);
        }

        void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType != DataControlRowType.DataRow) return;

            int age;
            if (int.TryParse(e.Row.Cells[1].Text, out age))
                if (age == 30)
                {
                    Button btnEdit = (Button) e.Row.FindControl("btnEdit");
                    btnEdit.Visible = false;
                }
        }

        private static List<Customer> GetCustomers()
        {
            List<Customer> results = new List<Customer>();

            results.Add(new Customer("Steve", 30));
            results.Add(new Customer("Brian", 40));
            results.Add(new Customer("Dave", 50));
            results.Add(new Customer("Bill", 25));
            results.Add(new Customer("Rich", 22));
            results.Add(new Customer("Bert", 30));

            return results;
        }
    }

    public class Customer
    {
        public string Name {get;set;}
        public int Age { get; set; }

        public Customer(string name, int age)
        {
            Name = name;
            Age = age;
        }
    }
}

在演示中,编辑按钮在客户年龄为 30 岁的那些行中不可见(HTML 标记不会发送到客户端)。

【讨论】:

    【解决方案2】:

    如果这是基于角色,您可以使用多视图面板,但不确定是否可以针对记录的属性执行相同操作。

    但是,您可以通过代码执行此操作。在您的 rowdatabound 事件中,您可以隐藏或显示其中的按钮。

    【讨论】:

      【解决方案3】:

      首先,将您的ButtonFieldCommandField 转换为TemplateField,然后将按钮的Visible 属性绑定到实现业务逻辑的方法:

      <asp:GridView runat="server" ID="GV1" AutoGenerateColumns="false">
          <Columns>
              <asp:BoundField DataField="Name" HeaderText="Name" />
              <asp:BoundField DataField="Age" HeaderText="Age" />
              <asp:TemplateField>
                  <ItemTemplate>
                      <asp:Button runat="server" Text="Reject" 
                      Visible='<%# IsOverAgeLimit((Decimal)Eval("Age")) %>' 
                      CommandName="Select"/>
                  </ItemTemplate>
              </asp:TemplateField>
          </Columns>
      </asp:GridView>
      

      然后,在后面的代码中,添加方法:

      protected Boolean IsOverAgeLimit(Decimal Age) {
          return Age > 35M;
      }
      

      这里的优点是您可以相当容易地测试IsOverAgeLimit 方法。

      【讨论】:

      • 正是我正在寻找的答案。很好,谢谢。您不只是喜欢那些文档不那么完善的 GridView 功能吗? :-)
      • @levi 我稍微编辑了答案,将命令名称(用于选择命令)包含在建议的按钮中。
      • @Marcel 是否会影响性能,因为按钮的可见性每次都会调用服务器端事件。如果是,请提出另一种方法
      • @clarifier 好吧,它每次都在调用方法背后的代码。这本身并不昂贵。但是,您应该注意该方法的实现。如果它很昂贵,这很容易总结出很大的成本。简单的比较应该没问题。 请务必使用分析工具。
      【解决方案4】:

      将CommandField转换为TemplateField,并根据字段的值(真/假)设置按钮的可见属性

      <asp:Button ID="btnSelect" 
      runat="server" Text="Select" 
      Visible='<%# DataBinder.Eval(Container.DataItem,"IsLeaf") %>'/>
      

      【讨论】:

        【解决方案5】:

        隐藏整个 GridView 列

        如果您想从表中完全删除列(即不仅仅是按钮),请使用合适的事件处理程序,例如对于OnDataBound 事件,然后隐藏目标GridView 上的相应列。选择一个只会为此控件触发一次的事件,即不是OnRowDataBound

        aspx:

        <asp:GridView ID="grdUsers" runat="server" DataSourceID="dsProjectUsers" OnDataBound="grdUsers_DataBound">
            <Columns>
                <asp:TemplateField HeaderText="Admin Actions">
                    <ItemTemplate><asp:Button ID="btnEdit" runat="server" text="Edit" /></ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="FirstName" HeaderText="First Name" />
                <asp:BoundField DataField="LastName" HeaderText="Last Name" />
                <asp:BoundField DataField="Telephone" HeaderText="Telephone" />
            </Columns>
        </asp:GridView>
        

        aspx.cs:

        protected void grdUsers_DataBound(object sender, EventArgs e)
        {
            try
            {
                // in this case hiding the first col if not admin
                if (!User.IsInRole(Constants.Role_Name_Admin))
                    grdUsers.Columns[0].Visible = false;
            }
            catch (Exception ex)
            {
                // deal with ex
            }
        }
        

        【讨论】:

          【解决方案6】:

          要有条件地控制模板/命令字段的视图,请使用 Gridview 的 RowDataBound 事件,例如:

              <asp:GridView ID="gv1" OnRowDataBound="gv1_RowDataBound"
                        runat="server" AutoGenerateColumns="False" DataKeyNames="Id" >
              <Columns>   
                  ...        
                     <asp:TemplateField HeaderText="Order Status" 
          HeaderStyle-HorizontalAlign="Center" ItemStyle-HorizontalAlign="Center"> 
                           <ItemTemplate> 
                                 <asp:Label ID="lblOrderStatus" runat="server"
          Text='<%# Bind("OrderStatus") %>'></asp:Label> 
                           </ItemTemplate>
                           <HeaderStyle HorizontalAlign="Center"></HeaderStyle>
                           <ItemStyle HorizontalAlign="Center"></ItemStyle>
                     </asp:TemplateField>  
                  ...
          
                      <asp:CommandField ShowSelectButton="True" SelectText="Select" />
          
              </Columns>
                          </asp:GridView>
          

          以下:

          protected void gv1_RowDataBound(object sender, GridViewRowEventArgs e)
              {
                  Label lblOrderStatus=(Label) e.Row.Cells[4].FindControl("lblOrderStatus");
          
                  if (lblOrderStatus.Text== "Ordered")
                  {
                      lblOrderStatus.ForeColor = System.Drawing.Color.DarkBlue;
                      LinkButton bt = (LinkButton)e.Row.Cells[5].Controls[0];
                      bt.Visible = false;
                      e.Row.BackColor = System.Drawing.Color.LightGray;
                  }
              }
          

          【讨论】:

          • 这正是我想要的
          【解决方案7】:

          请允许我分享我的方法,看看它的价值。对我来说,将命令字段转换为模板字段控件不是一种选择,因为命令字段带有内置功能,否则我必须自己创建,例如,当单击编辑时它会更改为“更新取消”,并且当点击编辑时,该行中的所有标签单元格都会变成文本框等。

          在我的方法中,您可以保持命令字段不变,然后您可以根据需要通过代码隐藏它。在此示例中,如果网格的“场景”字段显示 RowDataBound 事件的相关行的文本“实际”,我将隐藏它。

          protected void gridDetail_RowDataBound(object sender, GridViewRowEventArgs e)
              {   
                  if (e.Row.RowType == DataControlRowType.DataRow)
                  {
                      if (((Label)e.Row.FindControl("lblScenario")).Text == "Actual")
                      {
                          LinkButton cmdField= (LinkButton)e.Row.Cells[0].Controls[0];
                          cmdField.Visible = false;
                      }
              }}
          

          【讨论】:

          • 我几乎放弃了,只是将我的命令字段转换为模板字段,但我知道它可以做到,所以我继续寻找它。我认为这应该是正确的答案。 (尽管我仍然不确定提问者对声明性答案的含义。)
          • 是的,我更喜欢这种方法。在不假设哪个控件是哪个控件的情况下,您也可以循环并检查 CommandName
          • 我也同意这个答案最适合制定的问题。虽然将命令字段更改为模板字段确实有效(在大多数情况下 imo 更好) - 问题是如何专门隐藏命令字段。
          【解决方案8】:

          您可以根据 GridView 中的位置(索引)隐藏 CommandField 或 ButtonField。

          例如,如果您的 CommandField 位于第一个位置(索引 = 0),您可以在 GridView 的事件 RowDataBound 中添加以下代码来隐藏它:

          protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
          {
              if (e.Row.RowType == DataControlRowType.DataRow)
              {
                  ((System.Web.UI.Control)e.Row.Cells[0].Controls[0]).Visible = false;
              }
          }
          

          【讨论】:

            【解决方案9】:

            我做了一个非常简单的事情来启用或禁用命令按钮。下面是我的网格

            <asp:GridView ID="grdOrderProduct" runat="server" TabIndex="1" BackColor="White" BorderColor="#CEC9EF" CssClass="table table-striped dataTable table-bordered"
              OnRowEditing="grdOrderProduct_RowEditing" OnRowUpdating="grdOrderProduct_RowUpdating" OnRowDeleting="grdOrderProduct_RowDeleting" OnRowDataBound="grdOrderProduct_RowDataBound"
              Width="100%" CellPadding="3" CellSpacing="1" BorderWidth="0" AutoGenerateColumns="False">
                    <HeaderStyle />
                    <AlternatingRowStyle />
                    <Columns>
                    <asp:BoundField DataField="ProductSKU" ReadOnly="true" HeaderText="Product SKU" HeaderStyle-CssClass="headTb4" />
                     <asp:BoundField DataField="ProductName" ReadOnly="true" HeaderText="ProductName" HeaderStyle-CssClass="headTb4" />
                     <asp:BoundField DataField="QTY" HeaderText="QTY" HeaderStyle-CssClass="headTb4" />
                     <asp:BoundField DataField="Discount" HeaderText="Discount %" HeaderStyle-CssClass="headTb4" />
                     <asp:BoundField DataField="TPrice" HeaderText="MRP" ReadOnly="true" HeaderStyle-CssClass="headTb4" />
                      <asp:CommandField ShowEditButton="true" ButtonType="Image" EditImageUrl="~/Images/edit.png"
                              UpdateImageUrl="~/Images/gear.png" CancelText=" " HeaderStyle-CssClass="headTb4"
                              ShowDeleteButton="true" DeleteImageUrl="~/Images/delete.png"
                              HeaderText="Action" ItemStyle-HorizontalAlign="Center">
                 <HeaderStyle CssClass="headTb4" />
                 <ItemStyle HorizontalAlign="Center" />
                 </asp:CommandField>
               </Columns>
            <AlternatingRowStyle CssClass="odd" />
            <PagerStyle HorizontalAlign="Center" VerticalAlign="Top" Wrap="False" />
            

            在以下方法中我已经完成了更改

             protected void grdOrderProduct_RowDataBound(object sender, GridViewRowEventArgs e)
                {
                    if (e.Row.RowType == DataControlRowType.DataRow)
                    {                
            
                            foreach (ImageButton button in e.Row.Cells[5].Controls.OfType<ImageButton>())
                            {
                                if (button.CommandName == "Delete")
                                {
                                    button.Visible = false;
                                }
                            }                    
            
                    }
                }
            

            【讨论】:

              【解决方案10】:
              <asp:GridView ID="gv_Document" CssClass="gridstyle" runat="server" OnRowDataBound="gv_Document_RowDataBound" AutoGenerateColumns="false" DataKeyNames="SourceGUID,Source,FilePath" ShowHeaderWhenEmpty="false" OnRowDeleting="gv_Document_RowDeleting">
                 <Columns>
                     <asp:BoundField HeaderText="ItemID" DataField="ItemID" ItemStyle-CssClass="hidden-field" HeaderStyle-CssClass="hidden-field" />
                     <asp:BoundField HeaderText="SourceGUID" DataField="SourceGUID" ItemStyle-CssClass="hidden-field" HeaderStyle-CssClass="hidden-field" />
                     <asp:BoundField HeaderText="Source" DataField="Source" ItemStyle-CssClass="hidden-field" HeaderStyle-CssClass="hidden-field" />
                         <asp:TemplateField HeaderText="">
                             <ItemTemplate>
                                  <asp:HyperLink ID="hyperLink" runat="server" Target="_blank" NavigateUrl='<%# Bind("FilePath")%>'
                                                                              Text='<%# Bind("FileName")%>'>  </asp:HyperLink>
                             </ItemTemplate>
                         </asp:TemplateField>
                    <asp:BoundField HeaderText="Type" DataField="FileExtension" ItemStyle-CssClass="hidden-field" HeaderStyle-CssClass="hidden-field" />
                    <asp:BoundField HeaderText="Content type" DataField="FileMimeType" ItemStyle-CssClass="hidden-field" HeaderStyle-CssClass="hidden-field" />
                    <asp:BoundField HeaderText="File Path" DataField="FilePath" ItemStyle-CssClass="hidden-field" HeaderStyle-CssClass="hidden-field" />
                    <asp:CommandField ShowDeleteButton="True" DeleteText="Delete" />
                 </Columns>
              

              使用此代码从后面的代码中禁用 gridview 中的删除按钮。

              protected void gv_Document_RowDataBound(object sender, GridViewRowEventArgs e)
              { 
                  if (e.Row.RowType == DataControlRowType.DataRow)
                  {
                      ((LinkButton)e.Row.Cells[7].Controls[0]).Visible = false;            
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 2013-07-03
                • 2017-01-29
                • 1970-01-01
                • 2021-07-28
                • 1970-01-01
                • 1970-01-01
                • 2018-06-16
                • 1970-01-01
                • 2016-09-27
                相关资源
                最近更新 更多