3

I have a GridView which you can click on a row and it should call the SelectedIndexChanged method (which updates another part of the page based on which row was selected). I have done something similar to this before and it worked, but I can't seem to get the SelectedIndexChanged part to be called for some reason.

The page is held in a master page which has a form runat="server" tag, and an <asp:ScriptManager> tag

I am using e.Row.Attributes.Add("onclick", ClientScript.GetPostBackClientHyperlink(Me.gridMessages, "Select$" & e.Row.RowIndex)) to allow the SelectedIndexChanged to fire by clicking anywhere on the row.

To check that the code does work apart from that, I added a CommandField with a SelectButton and that successfully fires, but i would prefer to find a solution without having to use that.

code is below - any help would be appreciated. Thanks

GridView:

<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
    <ContentTemplate>
        <asp:HiddenField runat="server" ID="hdnScrollPosition" />
        <asp:GridView ID="gridMessages" runat="server" CssClass="gridView" AutoGenerateColumns="False"
            AllowPaging="true" GridLines="None" PageSize="10" ShowHeader="True"
            EmptyDataText="--No Messages Received--" Width="100%">
            <Columns>
                <asp:TemplateField HeaderText="Messages Received" HeaderStyle-HorizontalAlign="Left" HeaderStyle-CssClass="headerClass">
                    <ItemTemplate>
                        ....
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </ContentTemplate>
</asp:UpdatePanel>

Code-Behind:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If Not IsPostBack Then
        Me.gridMessages.DataSource = ...
        Me.gridMessages.DataBind()
    End If
End Sub

Protected Sub gridMessages_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gridMessages.RowDataBound
    If e.Row.RowType = DataControlRowType.DataRow Then
        e.Row.Attributes.Add("onmouseover", "this.style.backgroundColor='#D2E6F8'")
        e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor='#ffffff'")

        e.Row.Attributes.Add("onclick", "saveScrollPosition(); " & ClientScript.GetPostBackClientHyperlink(Me.gridMessages, "Select$" & e.Row.RowIndex))

    End If
End Sub

SelectedIndexChanged (which never fires):

Protected Sub gridMessages_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles gridMessages.SelectedIndexChanged
    Response.Redirect("test.aspx")
End Sub
jdtaylor
  • 334
  • 2
  • 5
  • 20

3 Answers3

4

Don't you need a column CommandField defined as a SelectButton? Then, your markup would look something like:

<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
    <ContentTemplate>
        <asp:HiddenField runat="server" ID="hdnScrollPosition" />
        <asp:GridView ID="gridMessages" runat="server" CssClass="gridView" AutoGenerateColumns="False"
            AllowPaging="true" GridLines="None" PageSize="10" ShowHeader="True"
            EmptyDataText="--No Messages Received--" Width="100%">
            <Columns>
                <asp:CommandField ShowSelectButton="true" ButtonType="Button" />
                <asp:TemplateField HeaderText="Messages Received" HeaderStyle-HorizontalAlign="Left" HeaderStyle-CssClass="headerClass">
                    <ItemTemplate>
                        ....
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </ContentTemplate>
</asp:UpdatePanel>

You didn't ask about this, but I always feel compelled to mention things like these two lines:

e.Row.Attributes.Add("onmouseover", "this.style.backgroundColor='#D2E6F8'")
e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor='#ffffff'")

This is a code smell. It's not a bad one, but mixing JavaScript attributes with VB/C# code is a habit you should break out of now. If you need to do something like this, add a CssClass property to your GridView and define those actions in CSS (or JavaScript/jQuery if CSS doesn't have enough events for you).


Edit:

Based on our discussion in comments, this looks like an inconsistency with the way the GridView can be modified. It may be related to the page/event lifecycle (somehow it's too late for ASP.NET to properly hook up the events?), and your best bet here is to switch from the SelectedIndexChanged event to SelectedIndexChanging.

jwheron
  • 2,553
  • 2
  • 30
  • 40
  • I'm trying to avoid having to actually use a button to select a row, which was why i added the extra attribute below the two above (thanks for the advice on splitting up the code - will do that). The e.Row.Attributes.Add("onclick", ClientScript.GetPostBackClientHyperlink(Me.gridMessages, "Select$" & e.Row.RowIndex)) line should work so that the gridview doesn't need the commandfield. thoughts? – jdtaylor Dec 02 '11 at 15:44
  • Hmm...I've never tried something like that. I'm not sure what ASP.NET will listen for if you don't have the button created (you may very well be right, and it might work just fine without the button). Maybe try creating the button to make sure you have the postback hyperlink stuff exactly right? That would be a good detail to edit back into the original question, I think. – jwheron Dec 02 '11 at 15:47
  • just added the button and the SelectedIndexChanged fires when using that. I've used the onclick attribute before and it worked, so am unsure why it doesn't with this – jdtaylor Dec 02 '11 at 15:50
  • btw thanks for the tweaks to the question, makes more sense now! – jdtaylor Dec 02 '11 at 15:52
  • No problem. I minored in English in college, so I have to make use of that education somehow. :) Does JavaScript generated by the button you added match what you were building in code-behind for the row itself? – jwheron Dec 02 '11 at 15:55
  • Yeah it matches, I tried removing it to see if that was the problem and it didn't make any difference. – jdtaylor Dec 02 '11 at 15:58
  • Does it work if you remove the call to `saveScrollPosition();`? I just tried this myself on one of my projects, and it worked properly in Firefox 8.0. Maybe it's a browser issue as well? – jwheron Dec 02 '11 at 16:04
  • I've removed that and it now works, but only if I keep the `CommandField` in. The strange thing though is it only fires when there is a `Response.Redirect("test.aspx")` in the `SelectedIndexChanged` If i put a `Response.Write("...")` or just change a label value `Me.lblName.Text = "this"` it doesn't fire and none of these change. Bit confusing why its only firing if there's a `Response.Redirect()` ! – jdtaylor Dec 02 '11 at 16:16
  • after looking through it, it turns out that the `SelectedIndexChanged` method doesn't like me using `Me.gridMessages.SelectedRow` whenever I do that it refuses to fire, but if its removed everything else works. Is there an alternative way to get the selected row index? – jdtaylor Dec 02 '11 at 17:04
  • Can you use the `SelectedIndexChanging` event instead? There, you'll have access to `e.NewSelectedIndex`, which you can use to access `gridMessages.Rows[e.NewSelectedIndex]`. – jwheron Dec 02 '11 at 18:34
  • Thanks - works perfectly with `SelectedIndexChanging` looks like all the errors are fixed now, thanks - you've helped me out alot! – jdtaylor Dec 02 '11 at 20:21
  • No problem at all -- I learned a few things in this experience myself. I'll update the answer according to our discussion here. – jwheron Dec 02 '11 at 20:24
1

I've been wrestling with the same issue...

It may not work in your scenario (or be a good thing to do at all) but try setting EnableEventValidation="false" for the page. This was the difference for me. Worked using either SelectedIndexChanged or SelectedIndexChanging events as mentioned above.

Stewart
  • 153
  • 3
  • 12
0

Use this:

e.Row.Attributes["onclick"]=ClientScript.GetPostBackEventReference(this.grvDetails,"Select$"+e.Row.RowIndex.ToString());
Unai Vivi
  • 3,073
  • 3
  • 30
  • 46
vijay
  • 58
  • 5