Question

My GridView basically displays a summarized version of data in the database.

What I want to do is set it up so that when you click anywhere in a row in the GridView, it should execute a set procedure that'll hide the panel that contains the GridView and display a panel that will show you the details of the item you clicked.

        <asp:Panel runat="server" ID="pnlList">
            <div class="rightalign">
                <asp:Label runat="server" ID="lblCount"></asp:Label>
            </div>

            <asp:GridView runat="server" ID="gvItems" DataKeyNames="mailid" 
                AutoGenerateColumns="false" onrowdatabound="gvItems_RowDataBound" 
                Width="100%" OnSelectedIndexChanged="gvItems_SelectedIndexChanged">
                <Columns>
                    <asp:TemplateField>
                        <ItemTemplate>
                            <asp:CheckBox runat="server" ID="chkSelect" />
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField>
                        <ItemTemplate>
                            <asp:Label runat="server" ID="lblStatus" Text='<%# DataBinder.Eval(Container.DataItem, "status") %>'></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:BoundField DataField="firstname" HeaderText="From" SortExpression="firstname" />
                    <asp:BoundField DataField="datesent" HeaderText="Date" SortExpression="datesent" DataFormatString="{0:yyyy/MM/dd HH:mm}" />
                    <asp:BoundField DataField="subject" HeaderText="Subject" SortExpression="subject" />
                </Columns>
            </asp:GridView>
        </asp:Panel>

        <asp:Panel runat="server" ID="pnlMail">
            <p>From: <asp:Label runat="server" ID="lblFrom"></asp:Label><br />
                Sent On: <asp:Label runat="server" ID="lblDate"></asp:Label><br />
                Subject: <asp:Label runat="server" ID="lblSubject"></asp:Label></p>
            <p><asp:Label runat="server" ID="lblMessage"></asp:Label></p>
        </asp:Panel>

I figured I'd use the SelectedIndexChanged event, but I'm not sure how to actually make it fire off clicks on the cells.

Here's the code I've got:

    protected void gvItems_SelectedIndexChanged(object sender, EventArgs e)
    {
        int index = gvItems.SelectedIndex;

        string mailid = gvItems.DataKeys[index].Value.ToString();

        getMailDetail(mailid);
        pnlMail.Visible = true;
    }

    protected void getMailDetail(string id)
    {
        int mailid = int.Parse(id);
        MySqlContext db = new MySqlContext();

        string sql = "select m.datesent, m.subject, m.message, u.firstname, u.lastname from mail m inner join users u on m.senderid = u.userid where m.mailid = @id";

        List<MySqlParameter> args = new List<MySqlParameter>();
        args.Add(new MySqlParameter() { ParameterName = "@id", MySqlDbType = MySqlDbType.Int32, Value = mailid });

        MySqlDataReader dr = db.getReader(sql, args);

        if (dr.HasRows)
        {
            dr.Read();

            lblFrom.Text = (string)dr["firstname"] + " " + (string)dr["lastname"];
            lblDate.Text = (string)dr["datesent"];
            lblSubject.Text = (string)dr["subject"];
            lblMessage.Text = (string)dr["message"];
        }
        dr.Close();
    }

How can I make clicks on the cells in a row fire an event that'll do the work I need done?

Any help will be appreciated!

Was it helpful?

Solution

I can see two possible solutions here. First - handle click on the row on client side, send Ajax request to some HttpHandler that will return you necessary mail details, and display the returned info. Steps to achieve this:

Assign a client side handler too row click:

protected void gvItems_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if(e.Row.RowType == DataControlRowType.DataRow)
    {
        e.Row.Attributes["onClick"] = "showMailDetails(" + DataBinder.Eval(e.Row.DataItem, "id") + ")";
    }
}

And define the client side function:

function showMailDetails(mailId) {
    $.get(
        url: 'url to HttpHandler here',
        data: {id: mailId},
        success: function(data) {
            var pnlMail = $('#<%= pnlMail.ClientID %>');
            // display data here

            pnlMail.show()
    });   
}

Another way is to handle click on client side and then emulate RowCommand event by doing something like this:

protected void gvItems_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if(e.Row.RowType == DataControlRowType.DataRow)
    {
        e.Row.Attributes["onClick"] = ""javascript:__doPostBack('" + gvItems.ClientID + "','MailDetailsCommand$" + DataBinder.Eval(e.Row.DataItem, "id") + "')";
    }
}

And then on server side go like you already did, just in RowComamnd handler:

protected void gvItems_RowCommand(object sender, GridViewCommandEventArgs e)
{
    if (e.CommandName == "MailDetailsCommand") {
    // ...
    }
}

Although I would not recommend this method - using _doPostBack manully is not considered as a best practice.

OTHER TIPS

you give a template field which consist the button or a button field and then you can the give the commandname as something and then you can use the gridview commandeventargs and based on the commandname you can do whatever you want, and you can use the OnRowCommand to fire an event :D hope this will help you .....

You can even go for adding the onclick attribute to the cell in the RowDataBound Event, if there are any restrictions of not having the button field or like that

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top