Multiple DataKeyNames in a GridView

2020-07-10 06:51发布

问题:

I have a GridView populated from an ObjectDataSource with two items in its DataKeyNames field. One is the primary key, ID, the other is a category field (the category field is used to add header rows to delineate categories).

Displaying works fine, but I'm trying to create a Delete action. The object's delete method only needs the ID field and in the ObjectDataSource even if I define the method as only needing an ID field, .net complains because it is looking for a method which has both the fields defined in DataKeyNames.

It works if I add a parameter for the category to the delete method, but it's annoying to have a parameter defined that isn't used for anything.

Can I configure the ObjectDataSource and GridView objects to have two values for DataKeyNames but specific which would should be passed to which methods?

The (simplified) definitions for the two objects are:

<asp:ObjectDataSource ID="ObjDS1" runat="server" SelectMethod="getAllItems" 
    TypeName="Items" DeleteMethod="deleteItem">
    <DeleteParameters>
        <asp:Parameter Name="ID" Type="Int32" />
       <!-- This shouldn't be necessary: -->
        <asp:Parameter Name="Category" Type="String" />
    </DeleteParameters>
</asp:ObjectDataSource>

<asp:GridView ID="gvJItems" runat="server" AutoGenerateColumns="False" DataKeyNames="ID,Category" 
    DataSourceID="ObjDS1">
        <Columns>
            <asp:BoundField DataField="ID" Visible="false"  HeaderText="ID" />
            <asp:BoundField DataField="Name" HeaderText="Name" ItemStyle-Width="85%"/>
            <asp:TemplateField>
                <ItemTemplate>
                    <asp:LinkButton ID="lbDelete" Runat="server" 
                        OnClientClick="return confirm('Are you sure you want to delete this?');"
                            CommandName="Delete">Delete</asp:LinkButton>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

回答1:

All of the DataKey values will always be passed to the Delete method because the fields named by DataKeyNames are intended to be the field or fields that uniquely identify that item in the GridView. They're often used for more than that to easily maintain extra fields on a per-row basis in ViewState as you are here, but doing so has the side-effect that you're seeing with the ObjectDataSource methods.

To answer your original question, no, you can't have Category be in DataKeyNames without having it be passed to the Delete method. You could maintain the value in ViewState by putting the value in a hidden input in your Template Column, though. It would be more work to get that value out than to ignore the parameter to the Delete method, though.



回答2:

I had the same problem with my gridview with an object datasource, how I handled this situation : I use StoredProcs in the SQL end. I added one more parameter into the store procedure, though I did not need that parameter. It worked fine



回答3:

You can remove them using the ObjectDataSource updating/deleting the event

void ODS_Updating(Object sender, ObjectDataSourceMethodEventArgs e)
{
  e.InputParameters.Remove("Type_ID");
  e.InputParameters.Remove("Document_ID");
  e.InputParameters.Remove("State_ID");
}

I am using the DataKeys for look-up purposes but I don't need them in my update procedure.



回答4:

When using the default declarative delete method, GridView will pass both values to the ObjectDataSource.

If you really don't like the extra parameter, an alternative is to cancel the declarative method and use your own one (you can remove the unnecessary parameter there), but it requires more code.