Search code examples
asp.netgridview

GridView EventHandler use when using a Repeater question / issue


I want to run some code, ideally, right before a GridView renders, though I could probably do it in the RowCreated or RowDataBound events.

My problem is that I'm creating multiple GridViews using a repeater. And the code I'd like to run needs to work with a Dictionary that is custom to each particular gridview that gets built. So, I'd like to pass a custom argument to whatever event I use.

Yet, I have to define the event within the single (templated) GridView's tag / structure itself (OnRowDataBound="").

So, how can I tell the code to call that event, but pass an extra argument?

Thanks!


Solution

  • The general approach then is for each repeater "row", then you can deal with the ONE GridView.

    In most cases, that event will be the repeater row data bound event.

    For example, I have a repeater that going to repeat a list of cites.

    And for each repeater, I THEN want a Gridview of hotels in each city.

    so,

    repeater-> feed out list of thing to repeat
        repeater->row data bound event - deal with ONE GridView
    

    Say this markup:

            Enter City(s) for Hotels: 
            <asp:TextBox ID="txtCity" runat="server" Width="500px">
            </asp:TextBox>
    
            <asp:Button ID="cmdShow" runat="server" 
                Text="Show Hotels "
                style="margin-left:30px"
                OnClick="cmdShow_Click" CssClass="btn"
                />
    
            <asp:Repeater ID="Repeater1" runat="server"
               OnItemDataBound="Repeater1_ItemDataBound"  >
                <ItemTemplate>
                    <div style="width: 50%">
                        <h3><%# $"Hotels For City = {Eval("City")}" %></h3>
                        <asp:GridView ID="GridView1"
                            runat="server" CssClass="table">
                        </asp:GridView>
                    </div>
                </ItemTemplate>
            </asp:Repeater>
    

    In above, the user can enter 1, or 10 cities.

    So we are to "repeat" the GridView for each city the user enters.

    Our code behind is thus this:

    Protected Sub cmdShow_Click(sender As Object, e As EventArgs)
    
        Dim rstMyCities As New DataTable
        rstMyCities.Columns.Add("City")
    
        Dim sCity As String = txtCity.Text.Replace(" ", "")
        For Each City As String In sCity.Split(",")
            Dim OneRow = rstMyCities.NewRow
            OneRow("City") = City
            rstMyCities.Rows.Add(OneRow)
        Next
    
        Repeater1.DataSource = rstMyCities
        Repeater1.DataBind()
    
    End Sub
    

    So, we make a list of City, and send that to the repeater.

    We get this:

    enter image description here

    So, now we deal with ONE grid at a time. And we use the Item Data Bound event of the repeater.

    Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
    
        If e.Item.ItemType = ListItemType.Item Or
                e.Item.ItemType = ListItemType.AlternatingItem Then
    
            Dim MyBindData As DataRowView = e.Item.DataItem
    
            Dim cmdSQL As New SqlCommand(
                "SELECT FirstName, LastName, City, HotelName, Description FROM tblHotelsA
                WHERE City = @City ORDER BY FirstName ")
    
            cmdSQL.Parameters.Add("@City", SqlDbType.NVarChar).Value = MyBindData("City")
    
            Dim GV As GridView = e.Item.FindControl("GridView1")
            GV.DataSource = MyRstP(cmdSQL)
            GV.DataBind()
    
        End If
    
    End Sub
    

    So, you don't mention "what" it is you want to pass to each GridView. Or perhaps you need to deal with EACH row of the GridView.

    However, at the end of the day, you deal with "whatever" it is you want in regards to the ONE GridView. And be it one GridView without a repeater, or 10 GridView inside of a repeater?

    There is no change in this "problem" and "solution".

    Now, let's say for each GridView, we want to highlight the row if the Hotel is active. Well, this is a 100% separate question, since it don't matter if you dealing with 1 GridView, or 20.

    The approach is the same, and for typical GridView formatting, then you use again the GridView data row binding event. So, in effect, just like we use the row data bind event for the repeater, we are able to do the same for each GridView, and again we can do whatever we want for each row of the Grid View.

    So, our repeater code to bind the GridView can say include the Active column I have for active hotels.

    So, then this:

    Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
    
        If e.Item.ItemType = ListItemType.Item Or
                e.Item.ItemType = ListItemType.AlternatingItem Then
    
            Dim MyBindData As DataRowView = e.Item.DataItem
    
            Dim cmdSQL As New SqlCommand(
                "SELECT FirstName, LastName, City, HotelName, Description, Active FROM tblHotelsA
                WHERE City = @City ORDER BY FirstName ")
    
            cmdSQL.Parameters.Add("@City", SqlDbType.NVarChar).Value = MyBindData("City")
    
            Dim GV As GridView = e.Item.FindControl("GridView1")
            GV.DataSource = MyRstP(cmdSQL)
            GV.DataBind()
    
        End If
    
    End Sub
    

    (I added the Active column to above).

    So, now in our GridView row data bind event, then I can do this:

    So, we add the row data bind event to the GV, say like this:

            <asp:Repeater ID="Repeater1" runat="server"
               OnItemDataBound="Repeater1_ItemDataBound"  >
                <ItemTemplate>
                    <div style="width: 50%">
                        <h3><%# $"Hotels For City = {Eval("City")}" %></h3>
                        <asp:GridView ID="GridView1"
                            runat="server" CssClass="table"
                            OnRowDataBound="GridView1_RowDataBound"
                            >
                        </asp:GridView>
                    </div>
                </ItemTemplate>
            </asp:Repeater>
    

    And now say let's highlight the row based on Active = true/false.

    This:

    Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs)
    
    
        If e.Row.RowType = DataControlRowType.DataRow Then
    
            Dim gData As DataRowView = e.Row.DataItem
    
            If gData("Active") = True Then
                e.Row.BackColor = System.Drawing.Color.LightSteelBlue
            End If
    
        End If
    
    
    End Sub
    

    You note unlike the repeater that requires a test for "alternating" row, the gridview does not require such a test.

    So, now we see this (any row in a gridview with Active = true gets a color setting).

    enter image description here

    So, yes, just setup a standard GridView row data bind event, and really how this works for one GV will for for 10 of them.

    In effect, your second question really does not require a repeater, but only that of dealing with ONE GridView, and what data you want to drive that GridView, and then of course what you want to do for each row of the GridView is again ONE row and ONE thing you deal with at a time.