1

My question is two-fold: firstly, is it a mistake by Microsoft that when the autogeneratecolumns=true attribute of an asp.net gridview is set, columns are generated even for fields listed in the datakeynames attribute? Surely that is contrary to the whole rationale for datakeys? Secondly, is there a way to use datakeys without having to explicitly list all the non-datakey columns in the grid as bound fields, which is tedious and bad for maintenance?

In the light of AVD's comment, I will give an example: suppose I have this query as the source for my grid

SELECT intAssessmentElementID, strModuleCode, strAssessmentElement, 
Weighting, intSemester, SubmissionDate FROM tblAssessmentElements

and I don't want to display intAssessmentElementID. Here is my gridview definition

        <asp:GridView ID="grdAssessmentElements" runat="server" DataKeyNames="intAssessmentElementID">
           <Columns>
           <asp:BoundField HeaderText="Module Code" DataField="strModuleCode" />
           <asp:BoundField HeaderText="Element" DataField="strAssessmentElement" />
           <asp:BoundField HeaderText="Weighting" DataField="Weighting" />
           <asp:BoundField HeaderText="Semester" DataField="intSemester" />
           <asp:BoundField HeaderText="Submission Date" DataField="SubmissionDate" />
            </Columns>
        </asp:GridView>

Writing out those bound fields is tedious, and if I add a field to the query, I have to remember to add it to the grid definition too. With autogeneratecolumns=true, the update would be automatic. But autogeneratecolumns=true generates all columns, even those listed in datakeynames. I think this is contralogical. I would like a way to use both autogeneratecolumns=true and datakeynames, but with the datakeynames columns not appearing. I have seen numerous suggestions to hide the columns after data bind, but they don't work for me and others When the columns are auto-generated, they don't appear to be available/generated even in PreRender.

Community
  • 1
  • 1
DJDave
  • 865
  • 1
  • 13
  • 28
  • Well, you need to set `DataKeyNames` property. When the DataKeyNames property is set, the GridView control automatically creates a DataKey object for each row in the control. https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.datakeys(v=vs.110).aspx – KV Prajapati Jun 04 '15 at 09:46

1 Answers1

2

The very definition of AutoGenerateColumns is as follows (emphasis mine):

Gets or sets a value indicating whether bound fields are automatically created for each field in the data source.

If you don't want to display all of the fields, you must manually create a DataField for each one you want to display. Unfortunately, AutoGenerateColumns and DataKeyNames are unaware of each other.

Another option for you is to use AutoGenerateColumns, but hide the cells you don't want to see as they are created. First, hook onto the RowCreated event.

<asp:GridView ID="grdAssessmentElements" runat="server"
    DataKeyNames="intAssessmentElementID"
    OnRowCreated="grdAssessmentElements_RowCreated">

Then in this event, hide the cell. The problem with this is that you must hardcode indexes. For example, if you know the first column is one you want to hide.

protected void grdAssessmentElements_RowCreated(object sender, GridViewRowEventArgs e)
{
    e.Row.Cells[0].Visible = False;
}

This still does not solve the problem of having to change the code as soon as you start returning a new column, however. As soon as you add a new column and you don't want to show it, you must add more code.

To answer your second question, you can use DataKeys whenever you want. You could use it with AutoGenerateColumns and hide the cells yourself. Or you could use it and explicitly list your columns.

I prefer listing each column. That way if the query ever changes without your knowledge, you know that your GridView will never display something it shouldn't. I have never found it to be as tedious as you seem to be thinking.

j.f.
  • 3,908
  • 2
  • 29
  • 42
  • 1
    j.f., your answer is certainly helpful since `e.Row.Cells[0].Visible = False;` successfully hides a column whereas a similar line to try to hide the whole column in PreRender doesn't. You cite the definition of AutoGenerateColumns - but do you think it is contralogical? – DJDave Jun 05 '15 at 14:08
  • No, not entirely. Though I had never thought about it the way you had until I saw your post. I always viewed `AutoGenerateColumns` as just a quick way to create a very simple GridView. I give it fields and it creates a GridView for me based on those fields. I've never actually used it before in a business setting, however. Stored procedures could always change at any time and potentially leave my GridView displaying sensitive information that it shouldn't. I always prefer to have control. – j.f. Jun 05 '15 at 14:17
  • Also, if `AutoGenerateColumns` were to work with `DataKeyNames`, I would like to somehow know that in advance - something like `AutoGenerateColumnsWithoutDataKeyNames`. If I auto generate my columns and put some data keys in there, and I start not seeing some columns, it may be difficult to understand why without reading the documentation of `AutoGenerateColumns`. The last thing you want is to confuse programmers that don't/can't read documentation. – j.f. Jun 05 '15 at 14:19
  • j.f. and also @DJDave - many years later I know, but trying this cell hiding code now unfortunately makes paging not work (no paging controls if I add this code, they come back if I remove it) :-( - the advice to just manually specify the columns remains good! – MikeBeaton Nov 18 '21 at 16:54