35

I have a gridview with multiple rows, each has a Update button and I need to pass 2 values when someone clicks on Update button. Aside from packing the arguments inside CommandArgument separated by commas (archaic and not elegant), how would I pass more than one argument?

<asp:LinkButton ID="UpdateButton" runat="server" CommandName="UpdateRow" CommandArgument="arg_value" Text="Update and Insert" OnCommand="CommandButton_Click" ></asp:LinkButton>

As a note, the values can't be retrieved from any controls on the page, so I am presently not seeking any design solutions.

2
  • 7
    The 'archaic' solution of using a delimiter is sometimes the easiest. Commented Mar 5, 2010 at 19:19
  • @sarsnake - i would accept Archana Motagi's answer Commented Aug 24, 2015 at 12:44

8 Answers 8

85

You can pass semicolon separated values as command argument and then split the string and use it.

<asp:TemplateField ShowHeader="false">
    <ItemTemplate>
       <asp:LinkButton ID="lnkCustomize" Text="Customize"  CommandName="Customize"  CommandArgument='<%#Eval("IdTemplate") + ";" +Eval("EntityId")%>'  runat="server"> 
       </asp:LinkButton>   
    </ItemTemplate>   
</asp:TemplateField>

at server side

protected void gridview_RowCommand(object sender, GridViewCommandEventArgs e)
{
      string[] arg = new string[2];
      arg = e.CommandArgument.ToString().Split(';');
      Session["IdTemplate"] = arg[0];
      Session["IdEntity"] = arg[1];
      Response.Redirect("Samplepage.aspx");
}
Sign up to request clarification or add additional context in comments.

2 Comments

The above worked for me. Only problem is you're missing the parameters in the Redirect() ASPX link. Try Response.Redirect("Samplepage.aspx?IdTemplate=" + Session["IdTemplate"].ToString().Trim() + "&IdEntity=" + Session["IdEntity"].ToString().Trim());
Being a pedant you don't need the .ToString(). CommandArgument is always a string, so: var argument = ((LinkButton)sender).CommandArgument.Split(';');
18

@Patrick's answer is a good idea, and deserves more credit!. You can have as many data items as you want, they are all separated, and can be used client side if necessary.

They can also be added declaratively rather than in code. I just did this for a GridView like this:

<asp:TemplateField HeaderText="Remind">
  <ItemTemplate>
    <asp:ImageButton ID="btnEmail"  
        data-rider-name="<%# ((Result)((GridViewRow) Container).DataItem).Rider %>"
        data-rider-email="<%# ((Result)((GridViewRow) Container).DataItem).RiderEmail %>"
        CommandName="Email" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/images/email.gif" />
  </ItemTemplate> 
</asp:TemplateField>

In the RowCommand, you do this:

void gvMyView_RowCommand(object sender, GridViewCommandEventArgs e)
{
    if (e.CommandName == "Email")
    {
        var btnSender = (ImageButton)e.CommandSource;
        var riderName = btnSender.Attributes["data-rider-name"];
        var riderEmail = btnSender.Attributes["data-rider-email"];
        // Do something here
    }
}

So much cleaner than hacking all the values together with delimiters and unpacking again at the end.

Don't forget to test/clean any data you get back from the page, in case it's been tampered with!

1 Comment

I like this approach, it's as close as you'll get to having the items strongly typed, using commas and substring to separate this kind of info, although workable, can become a mess. You need have inherent knowledge of what each part of the argument is, using "data-" containers is safer and makes the code much more readable.
16

After poking around it looks like Kelsey is correct.

Just use a comma or something and split it when you want to consume it.

1 Comment

10

My approach is using the attributes collection to add HTML data- attributes from code behind. This is more inline with jquery and client side scripting.

// This would likely be done with findControl in your grid OnItemCreated handler
LinkButton targetBtn = new LinkButton();


// Add attributes
targetBtn.Attributes.Add("data-{your data name here}", value.ToString() );
targetBtn.Attributes.Add("data-{your data name 2 here}", value2.ToString() );

Then retrieve the values through the attribute collection

string val = targetBtn.Attributes["data-{your data name here}"].ToString();

Comments

5

A little more elegant way of doing the same adding on to the above comment ..

<asp:GridView ID="grdParent" runat="server" BackColor="White" BorderColor="#DEDFDE"
                           AutoGenerateColumns="false"
                            OnRowDeleting="deleteRow"
                         GridLines="Vertical">
      <asp:BoundField DataField="IdTemplate" HeaderText="IdTemplate" />
      <asp:BoundField DataField="EntityId" HeaderText="EntityId"  />
    <asp:TemplateField ShowHeader="false">
        <ItemTemplate>
           <asp:LinkButton ID="lnkCustomize" Text="Delete"  CommandName="Delete"  CommandArgument='<%#Eval("IdTemplate") + ";" +Eval("EntityId")%>'  runat="server"> 
           </asp:LinkButton>   
        </ItemTemplate>   
    </asp:TemplateField>
     </asp:GridView>

And on the server side:

protected void deleteRow(object sender, GridViewDeleteEventArgs e)
{
    string IdTemplate= e.Values["IdTemplate"].ToString();
    string EntityId = e.Values["EntityId"].ToString();

   // Do stuff..
}

1 Comment

This only works if you want the IdTemplate and EntityId fields displayed in your grid. The values you places in the CommandArgument is never actually used.
2

Either store it in the gridview datakeys collection, or store it in a hidden field inside the same cell, or join the values together. That is the only way. You can't store two values in one link.

Comments

0

If you want to pass two values, you can use this approach

<asp:LinkButton ID="RemoveFroRole" Text="Remove From Role" runat="server"
CommandName='<%# Eval("UserName") %>' CommandArgument='<%# Eval("RoleName") %>'
 OnClick="RemoveFromRole_Click" />

Basically I am treating {CommmandName,CommandArgument} as key value. Set both from database field. You will have to use OnClick event and use OnCommand event in this case, which I think is more clean code.

Comments

0

You can split the parameters using a separator (that must not be inside the parameter values - ex. "|"). Names of parameters must be valid names of the data source. Single quotes for the command arguments, and double quotes for the names of the parameters.

<%-- BUTTON VIEWCMD --%>
<asp:TemplateField HeaderText="" SortExpression="" ItemStyle-CssClass="widthP07 textAlignCenter">
    <ItemTemplate>
        <asp:Button ID="ButtonVIEWCMD" runat="server" Text="View Detail"
         CommandName="VIEWCMD" 
         CommandArgument='<%# Eval("param1") + "|" + Eval("param2") + "|" + Eval("param3") %>' />
                        
    </ItemTemplate>
</asp:TemplateField>

server code

/// <summary>
/// SET - Process GridView Row Commands
/// </summary>
protected void GridView_RowCommand(object sender, GridViewCommandEventArgs e)
{
    // INIT 
    string tempArguments = string.Empty;

    try
    {
        // CTRL - gridview row click
        switch (e.CommandName)
        {
            case "VIEWCMD":
                // GET 
                tempArguments = (string)(e.CommandArgument);
                // GET 
                string[] tempParam = tempArguments.Split('|');

                // GET 
                // tempParam[0];
                // tempParam[1];
                // tempParam[2];
                
                // .........

                break;

            default:
                break;
        }
    }
    catch (Exception ex)
    {
        // ERR .......
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.