Как скрыть столбцы в ASP.NET GridView с автоматически сгенерированными столбцами?

GridView1.Columns.Count всегда равен нулю даже SqlDataSource1.DataBind();

Но с сеткой все в порядке

я могу сделать

for (int i = 0; i < GridView1.HeaderRow.Cells.Count;i++)

Я переименовываю заголовки запроса здесь, но

GridView1.Columns[i].Visible = false;

Я не могу использовать его, потому что GridView1.Columns.Count равен 0.

Так как я могу их скрыть?

11 ответов

Решение

Попробуйте положить e.Row.Cells[0].Visible = false; внутри RowCreated событие вашей сетки.

protected void bla_RowCreated(object sender, GridViewRowEventArgs e)
{
    e.Row.Cells[0].Visible = false; // hides the first column
}

Таким образом, он автоматически скрывает весь столбец.

У вас нет доступа к сгенерированным столбцам через grid.Columns[i] в вашей сетке DataBound событие.

Коллекция Columns заполняется только тогда, когда AutoGenerate Columns = false, и вы вручную генерируете столбцы.

Хороший обходной путь для этого - динамическое заполнение коллекции Columns до установки свойства DataSource и вызова DataBind().

У меня есть функция, которая вручную добавляет столбцы на основе содержимого таблицы данных, которую я хочу отобразить. После того, как я это сделал (а затем установил DataSource и вызвал DataBind(), я могу использовать коллекцию Columns, и значение Count является правильным, и я могу включать и выключать видимость столбца, как я изначально хотел.

static void AddColumnsToGridView(GridView gv, DataTable table)
{
    foreach (DataColumn column in table.Columns)
    {
        BoundField field = new BoundField();
        field.DataField = column.ColumnName;
        field.HeaderText = column.ColumnName;
        gv.Columns.Add(field);
    }
}

Примечание. Это решение работает только в том случае, если GridView столбцы известны заранее.

Похоже, вы используете GridView с AutoGenerateColumns=true, который является значением по умолчанию. Я рекомендую настройку AutoGenerateColumns=false и добавление столбцов вручную:

<asp:GridView runat="server" ID="MyGridView"
    AutoGenerateColumns="false" DataSourceID="MySqlDataSource">
    <Columns>
        <asp:BoundField DataField="Column1" />
        <asp:BoundField DataField="Column2" />
        <asp:BoundField DataField="Column3" />
    </Columns>
</asp:GridView>

И только включить BoundField для каждого поля, которое вы хотите отобразить. Это даст вам максимальную гибкость с точки зрения отображения данных.

У меня возникла та же проблема - нужно, чтобы AutogenerateColumns моего элемента управления GridView были 'true' из-за его привязки к источнику данных SQL, и поэтому мне нужно было скрыть некоторые столбцы, которые не должны отображаться в элементе управления GridView.

Чтобы сделать это, добавьте некоторый код в событие _RowDataBound вашего GridView, например, следующее (предположим, что идентификатор вашего GridView равен = 'MyGridView'):

protected void MyGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        e.Row.Cells[<index_of_cell>].Visible = false;
    }
}

Это отлично сработает;-)

В rowdatabound метод для 2-го столбца

GridView gv = (sender as GridView);
gv.HeaderRow.Cells[2].Visible = false;
e.Row.Cells[2].Visible = false;

Вы должны выполнить GridView1.Columns[i].Visible = false; после того, как сетка была привязана к данным.

Попробуйте это, чтобы скрыть столбцы в ASP.NET GridView с автоматически сгенерированными столбцами, и RowDataBound/RowCreated тоже работают.

Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound

    If e.Row.RowType = DataControlRowType.DataRow Or _
        e.Row.RowType = DataControlRowType.Header Then   // apply to datarow and header 

        e.Row.Cells(e.Row.Cells.Count - 1).Visible = False // last column
        e.Row.Cells(0).Visible = False  // first column

    End If
End Sub

Protected Sub GridView1_RowCreated(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowCreated

    If e.Row.RowType = DataControlRowType.DataRow Or _
        e.Row.RowType = DataControlRowType.Header Then

        e.Row.Cells(e.Row.Cells.Count - 1).Visible = False
        e.Row.Cells(0).Visible = False

    End If
End Sub

@nCdy: index_of_cell следует заменить целым числом, соответствующим порядковому номеру ячейки, которую вы хотите скрыть в коллекции.Cells.

Например, предположим, что ваш GridView представляет следующие столбцы:

КОНТАКТНОЕ ИМЯ | КОНТАКТНЫЙ НОМЕР | CUSTOMERID | АДРЕСНАЯ ЛИНИЯ 1 | ПОСТ-КОД

И вы хотите, чтобы столбец CUSTOMERID не отображался. Поскольку индексы коллекций основаны на 0, индекс вашего столбца CUSTOMERID равен..........? Это верно, 2!! Отлично. Теперь... угадайте, что вы должны положить туда, чтобы заменить ' index_of_cell '??

Я нашел ответ Стива Хибберта очень полезным. Проблема, которую описывал OP, - это проблема AutoGeneratedColumns в GridView.

В этом случае вы можете указать, какие столбцы будут "видимыми", а какие будут скрыты при привязке таблицы данных в коде.

Например: Gridview находится на странице следующим образом.

<asp:GridView ID="gv" runat="server" AutoGenerateColumns="False" >
</asp:GridView>

И затем в коде за функцию PopulateGridView вызывается во время события загрузки страницы.

protected void PopulateGridView()
{
    DataTable dt = GetDataSource();
    gv.DataSource = dt;
    foreach (DataColumn col in dt.Columns)
    {
        BoundField field = new BoundField();
        field.DataField = col.ColumnName;
        field.HeaderText = col.ColumnName;
        if (col.ColumnName.EndsWith("ID"))
        {
            field.Visible = false;
        }
        gv.Columns.Add(field);
    }
    gv.DataBind();
}

Выше GridView AutoGenerateColumns имеет значение False, а кодовая область используется для создания связанных полей. Одним из них является получение источника данных как источника данных через собственный процесс, который я здесь обозначил GetDataSource(). Затем один перебирает коллекцию столбцов данных. Если имя столбца соответствует заданным критериям, вы можете соответствующим образом установить видимое свойство связанного поля. Затем вы привязываете данные к виду сетки. Это очень похоже на AutoGenerateColumns="True", но у вас есть критерии для столбцов. Этот подход наиболее полезен, когда критерии скрытия и скрытия основаны на имени столбца.

Выполните итерацию по строкам GridView и сделайте ячейки целевых столбцов невидимыми. В этом примере я хочу, чтобы столбцы 4-6 были видны как есть, поэтому мы пропускаем их:

foreach (GridViewRow row in yourGridView.Rows)
   {
     for (int i = 0; i < rows.Cells.Count; i++)
     {
        switch (i)
        {
           case 4:
           case 5:
           case 6:
              continue;
        }
        row.Cells[i].Visible = false;
     };
   };

Затем вам нужно будет удалить заголовки столбцов отдельно (имейте в виду, что удаление ячеек заголовков изменяет длину GridView после каждого удаления):

grdReportRole.HeaderRow.Cells.RemoveAt(0);

Как говорили другие, событие RowDataBound или RowCreated должно работать, но если вы хотите избежать объявления событий и поместить весь код чуть ниже вызова функции DataBind, вы можете сделать следующее:

GridView1.DataBind()
If GridView1.Rows.Count > 0 Then
    GridView1.HeaderRow.Cells(0).Visible = False
    For i As Integer = 0 To GridView1.Rows.Count - 1
        GridView1.Rows(i).Cells(0).Visible = False
    Next
End If

Аналогичен принятому ответу, но позволяет использовать ColumnNames и привязывается к RowDataBound().

Dictionary<string, int> _headerIndiciesForAbcGridView = null;

protected void abcGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (_headerIndiciesForAbcGridView == null) // builds once per http request
    {
        int index = 0;
        _headerIndiciesForAbcGridView = ((Table)((GridView)sender).Controls[0]).Rows[0].Cells
            .Cast<TableCell>()
            .ToDictionary(c => c.Text, c => index++);
    }

    e.Row.Cells[_headerIndiciesForAbcGridView["theColumnName"]].Visible = false;
}

Не уверен, что это работает с RowCreated().

Другие вопросы по тегам