Подтвердить что ты не робот

Условно скрыть CommandField или ButtonField в Gridview

У меня есть GridView отображение записей людей. Я хочу условно показать CommandField или ButtonField на основе некоторого свойства базовой записи. Идея состоит в том, чтобы разрешить выполнение команды только для определенных людей.

Каков наилучший способ сделать это? Я бы предпочел декларативное решение процедурного.

4b9b3361

Ответ 1

Сначала преобразуйте ButtonField или CommandField в 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.

Ответ 2

это можно сделать, если событие 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;
        }
    }
}

В демонстрации кнопка "Редактировать" не отображается (разметка HTML не отправляется клиенту) в тех строках, где возраст клиента равен 30.

Ответ 3

Позвольте мне поделиться своим подходом с тем, что стоит. Для меня преобразование командного поля в элемент управления шаблоном не является опцией, так как поле commandfield имеет встроенную функциональность, которую я в противном случае должен был бы создать самостоятельно, например, тот факт, что при нажатии "Редактировать" он меняет значение "Отменить обновление" и что при нажатии кнопки "Правка" все ячейки в строке, которые являются метками, становятся текстовыми полями и т.д.

В моем подходе вы можете оставить поле команды как есть, тогда вы можете скрыть его по мере необходимости с помощью кода. В этом примере я скрываю это, если поле "Сценарий" сетки показывает текст "Фактический" для соответствующей строки события 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;
            }
    }}

Ответ 4

Скрыть всю колонку 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
    }
}

Ответ 5

Преобразуйте CommandField в TemplateField и установите видимое свойство кнопки в зависимости от значения поля (true/false)

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

Ответ 6

Чтобы условно контролировать представление полей Template/Command, используйте событие RowDataBound для Gridview, например:

    <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 вы можете скрыть или показать в нем кнопку.

Ответ 8

Вы можете скрыть CommandField или ButtonField на основе позиции (индекса) в GridView.

Например, если ваш CommandField находится в первой позиции (index = 0), вы можете скрыть его, добавив следующий код в событие RowDataBound для GridView:

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

        }
    }