Solved

Datagrid paging un a User Control (VB) - URGENT

Posted on 2004-10-22
680 Views
Last Modified: 2009-12-16
I have a master page (srchstat.aspx) that loads a user control (qqhead.ascx). qqhead.ascx displays a logo and loads another user control (search.ascx). search.ascx allows the user to enter a search string in a text box. When the user clicks the search button another user control (results.ascx) is called the value of the texbox within seatch.ascx is read and passed to a stored procedure. results.ascx has a datagrid within it that is bound to the dataset returned by the stored procedure. I have tried to implement paging however, the datagrid not displayed when one of the page number links is clicked.

ANy ideas?


THE CODE:

search.ascx - HTML

<%@ Control Language="vb" AutoEventWireup="false" Codebehind="search.ascx.vb" Inherits="qqsts.search" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
<TABLE id="Table1" cellSpacing="0" cellPadding="0" width="300" border="0">
      <TR>
            <TD style="WIDTH: 214px"><asp:label id="Label2" runat="server">Surname or Post Code</asp:label></TD>
            <TD></TD>
            <TD></TD>
      </TR>
      <TR>
            <TD style="WIDTH: 214px"><asp:textbox id="TbSrch" runat="server"></asp:textbox><asp:requiredfieldvalidator id="RequiredFieldValidator1" runat="server" ControlToValidate="TbSrch" ErrorMessage="*"></asp:requiredfieldvalidator><asp:regularexpressionvalidator id="RegularExpressionValidator1" runat="server" ControlToValidate="TbSrch" ErrorMessage="*"
                        ValidationExpression="[0-9a-zA-Z\s]*"></asp:regularexpressionvalidator></TD>
            <TD><asp:button id="btnSearch" runat="server" Text="Search"></asp:button></TD>
            <TD></TD>
      </TR>
</TABLE>
<asp:placeholder id="plhResults" Runat="server"></asp:placeholder>

Search.ascx - Code Behind

Imports System.Data.OleDb
Imports System.Reflection
Public Class search
    Inherits System.Web.UI.UserControl


#Region " Web Form Designer Generated Code "

    'This call is required by the Web Form Designer.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

    End Sub
    Protected WithEvents TextBox1 As System.Web.UI.WebControls.TextBox
    Protected WithEvents Button1 As System.Web.UI.WebControls.Button
    Protected WithEvents Label1 As System.Web.UI.WebControls.Label
    Protected WithEvents btnSrch As System.Web.UI.WebControls.Button
    Protected WithEvents Label2 As System.Web.UI.WebControls.Label
    Protected WithEvents btnSearch As System.Web.UI.WebControls.Button
    Protected WithEvents plhPolicy As System.Web.UI.WebControls.PlaceHolder
    Protected WithEvents plhSearch As System.Web.UI.WebControls.PlaceHolder
    Protected WithEvents plhResults As System.Web.UI.WebControls.PlaceHolder
    Protected WithEvents TbSrch As System.Web.UI.WebControls.TextBox
    Protected WithEvents RequiredFieldValidator1 As System.Web.UI.WebControls.RequiredFieldValidator
    Protected WithEvents RegularExpressionValidator1 As System.Web.UI.WebControls.RegularExpressionValidator

    'NOTE: The following placeholder declaration is required by the Web Form Designer.
    'Do not delete or move it.
    Private designerPlaceholderDeclaration As System.Object

    Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: This method call is required by the Web Form Designer
        'Do not modify it using the code editor.
        InitializeComponent()
    End Sub

#End Region

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here
       
        'Load the control if details page if we are requested by testing the value of the

        If Request.QueryString("disp") <> "" Then
            Dim ctlControl As Control
            plhResults.Controls.Clear()
            ctlControl = LoadControl("Details.ascx")
            plhResults.Controls.Add(ctlControl) ' Re-using this ID. It is used below for search results
        End If


    End Sub

    Private Sub btnSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSrch.Click, btnSearch.Click


        Dim ctlControl As Control
        plhResults.Controls.Clear() 'Clear previous details information (details.ascx)
        'Load and add the results control
        ctlControl = LoadControl("results.ascx")
        plhResults.Controls.Add(ctlControl)


    End Sub
    'Return the Text property of the textbox's text value on this user control
    Public ReadOnly Property srchTxt() As String

        Get
            Return TbSrch.Text
        End Get

    End Property

End Class


Results.ascx - HTML
<%@ Control Language="vb" AutoEventWireup="false" Codebehind="results.ascx.vb" Inherits="qqsts.results" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
<br>
<asp:label id="LblFileInfo" runat="server">Label</asp:label>
<asp:datagrid id="DgPolicy"  runat="server" AllowPaging="True" Width="736px" BorderWidth="1px"
      BorderStyle="Solid" BorderColor="LightSteelBlue" AutoGenerateColumns="False" PageSize="6">
      <FooterStyle HorizontalAlign="Right"></FooterStyle>
      <ItemStyle CssClass="DataGridItem"></ItemStyle>
      <AlternatingItemStyle CssClass="DataGridAltItem"></AlternatingItemStyle>
      <HeaderStyle CssClass="DataGridHeader"></HeaderStyle>
      <Columns>
            <asp:HyperLinkColumn />
            <asp:TemplateColumn HeaderText="Address">
                  <HeaderStyle></HeaderStyle>
                  <HeaderTemplate>
                        <b>Address</b>
                  </HeaderTemplate>
                  <ItemTemplate>
                        <%# DataBinder.Eval(Container.DataItem, "Hadd1") %>
                  </ItemTemplate>
            </asp:TemplateColumn>
            <asp:BoundColumn HeaderText="Premium" DataField="HPremium" DataFormatString="{0:c}"></asp:BoundColumn>
            <asp:TemplateColumn HeaderText="Start Date">
                  <HeaderStyle></HeaderStyle>
                  <HeaderTemplate>
                        <b>Start Date</b>
                  </HeaderTemplate>
                  <ItemTemplate>
                        <%# GetSchedDate(DataBinder.Eval(Container.DataItem, "HSchedDate")) %>
                  </ItemTemplate>
            </asp:TemplateColumn>
      </Columns>
      <PagerStyle HorizontalAlign="Center" CssClass="DataGridPager" Mode="NumericPages"></PagerStyle>
</asp:datagrid>

Results.acx - Code Behind

Imports System.Web.UI.WebControls
Imports Microsoft.ApplicationBlocks.Data
Imports System.Data.SqlClient
Imports System.io
'Imports System.Reflection

Public Class results
    Inherits System.Web.UI.UserControl


#Region " Web Form Designer Generated Code "

    'This call is required by the Web Form Designer.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

    End Sub
    Protected WithEvents DgPolicy As System.Web.UI.WebControls.DataGrid
    Protected WithEvents LblFileInfo As System.Web.UI.WebControls.Label

    'NOTE: The following placeholder declaration is required by the Web Form Designer.
    'Do not delete or move it.
    Private designerPlaceholderDeclaration As System.Object

    Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: This method call is required by the Web Form Designer
        'Do not modify it using the code editor.
        InitializeComponent()
    End Sub

#End Region

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here

        If Not dgPolicyBind() Then Exit Sub
        LblFileInfo.Text = "Last Updated: " + File.GetLastWriteTime(ConfigurationSettings.AppSettings("DBStatusPath") + ConfigurationSettings.AppSettings("DBStatusName"))


    End Sub
    Protected Sub DGPolicy_ItemDataBound(ByVal sender As Object, ByVal e As DataGridItemEventArgs) Handles DgPolicy.ItemDataBound
        '----------------------------------------------------------------------------------------------------------
        ' BIND GRID DATA ITEMS: Handles hgMyGrid.ItemDataBound
        '----------------------------------------------------------------------------------------------------------
        ' Add events/alerts to grid items
        '  Only applies to Item / Alt Items (ie: not header, footer rows)

        '  Adds mouseover highlight to rows.

        '----------------------------------------------------------------------------------------------------------
        If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
            ' Build the Hyperlink.
            ' Could have used Template Column but they are a bit messy, ties up
            ' HTML and code and code behind. the Hyperlink Column with DataNavigateUrlFormatString
            ' Will not work as we need to pass two items in the URL

            Dim hl As HyperLink = e.Item.Cells(0).Controls(0)
            Dim Temp = DataBinder.Eval(e.Item.DataItem, "CustSur1")
            hl.Text = IIf(Not IsDBNull(Temp), Temp, "")
            Dim navUrl As String
            navUrl = "../pa/srchstat.aspx?ID=" + Request.QueryString("ID") & "&DISP=" & _
                      Server.UrlEncode(DataBinder.Eval(e.Item.DataItem, "HQuoRef"))
            hl.NavigateUrl = navUrl
            'Add mouseover highlights to rows:
            If e.Item.ItemType = ListItemType.Item Then
                e.Item.Attributes.Add("onmouseover", "this.style.backgroundColor='#dcdcea';this.style.color='mediumblue'")
                e.Item.Attributes.Add("onmouseout", "this.style.backgroundColor='#EEEEEE';this.style.color='navy'")


            Else
                e.Item.Attributes.Add("onmouseover", "this.style.backgroundColor='#dcdcea';this.style.color='mediumblue'")
                e.Item.Attributes.Add("onmouseout", "this.style.backgroundColor='Gainsboro';this.style.color='navy'")
            End If

        End If
    End Sub

    Private Function dgPolicyBind() As Boolean
        dgPolicyBind = False
        Dim ctl As search = CType(Page, srchstat).UCtlHeader.FindControl("UCtlsearch")
        Dim srchTxt As String = ctl.srchTxt

        ' Get a dataset representing a list of Status's that match the search string
        Dim spName As String = "spGetStatus"
        Dim conn As String = ConfigurationSettings.AppSettings("DBQQStatus")
        Dim storedParams(1) As SqlParameter
        storedParams = SqlHelperParameterCache.GetSpParameterSet(conn, spName)
        storedParams(0).Value = srchTxt

        Dim ds As DataSet = SqlHelper.ExecuteDataset(conn, CommandType.StoredProcedure, spName, storedParams)

        DgPolicy.DataSource = ds
        DgPolicy.DataBind()
        dgPolicyBind = True
    End Function
    Protected Sub DGPolicy_Page(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridPageChangedEventArgs) Handles DgPolicy.PageIndexChanged
        '----------------------------------------------------------------------------------------------------------
        ' PAGE GRID DATA: Handles hgMyGrid.PageIndexChanged
        '----------------------------------------------------------------------------------------------------------
        ' Handles pageing on the data grid by setting current page index to the requested page index
        '----------------------------------------------------------------------------------------------------------
        'litErrMessage.Text = ""                             'Clear any existing error message
        DgPolicy.CurrentPageIndex = e.NewPageIndex          'Set page index
        If Not dgPolicyBind() Then Exit Sub 'Refresh data
    End Sub
 
   
0
Question by:BJM1M
    16 Comments
     
    LVL 33

    Expert Comment

    by:raterus
    ahh, dynamic controls that you add with ".controls.add(blah)", aren't persisted across postbacks.  It would probably be better for you to enable/disable visibility on your usercontrols, but have them all declared somewhere in the html source.  Dynamic controls tend to be a pain to deal with if you aren't careful.

    If you want to keep with dynamic controls, you will have to recreate them on each postback, that means the code below will have to ran everytime the page posts back and you still want to show that datagrid..see why dynamic controls are a pain :-)

            Dim ctlControl As Control
            plhResults.Controls.Clear() 'Clear previous details information (details.ascx)
            'Load and add the results control
            ctlControl = LoadControl("results.ascx")
            plhResults.Controls.Add(ctlControl)
    0
     

    Author Comment

    by:BJM1M
    O.K, I've done that and indeed, I did try it before but what happens is that the DataGrid is displayed which is great but when you selevt one of the page number links the value retrieved from the search textbox is lost i.e "nothing" therefore the SQL returns everything rather than the original dataset. I guess this has something to do with the tbsearch.text value not being persisted between postbacks? If so, how can I retain the original value?

    0
     
    LVL 33

    Expert Comment

    by:raterus
    I don't see the tbsearch control you are talking about.  But if you are creating it dynamically it will dissapear just like the usercontrols did.  Again I would suggest you get rid of all these dynamic controls, I don't think you need them for a page like this.  Add them all to the source page and set their visible property to true/false based on what you want to see.
    0
     

    Author Comment

    by:BJM1M
    Firstly,  the text box used in search.ascx has an id of Tbsrch and not as stated before. The reason why I am using User Controls is that it makes it easier to maintain as these pages will form the basis of a generic web site to be used as a framework for other site. Can you assist by giving me a pointer as to the most appropriate way to persist the value of the textbox Tbsrch? Should I save it as a viewstate?
    0
     
    LVL 28

    Expert Comment

    by:mmarinov
    Hi BJM1M,

    i think the problem is whith the order of executing the events of your user controls
    when you click on search button, events will execute like this:

    aspx:Page_Load
    ascx(search):Page_Load
    ascx(details):Page_Load
    ascx(search):btnSearch_Click
    ascx(results):Page_Load ( bind the grid with initial values - not paging )
    ascx(results):DGPolicy_ItemDataBound

    when you press the page number, order is

    aspx:Page_Load
    ascx(search):Page_Load
    ascx(details):Page_Load
    the results control is not create

    you can check this by debugging the events

    B..M
    0
     

    Author Comment

    by:BJM1M
    I'm not ure of the point that you are trying to make. Firstly the details control is only called if the hyperlink of the row of the datagrid wirhin results.ascx is clicked, therefore, until such time the order will be:

    aspx:Page_Load
    ascx(search):Page_Load
    ascx(results):Page_Load ( bind the grid with initial values - not paging )
    ascx(results):DGPolicy_ItemDataBound

    Nonetheless, can you help me?
    0
     
    LVL 28

    Expert Comment

    by:mmarinov
    the point is that because of results is dynamically created control you HAVE TO create it every time
    when you click the search button the results controls is created within the btnClick event
    but the next time when you press on page number the btnClick event doesn't fired and the results control is not created

    you can check this by click on any other control on your page ( except the bntsearch )

    so why don't you create the controls at design time with property visible=false
    and then in btnsearch just to set visible = false

    the dynamically created controls has to be created every time because they do not excist in the viestate and when the page is showing again it does not have the user control in it's state and can not loaded it

    B>.M
    0
     

    Author Comment

    by:BJM1M
    Maybe, I'm a bit slow on the take, but I've added the code to load the results within thr page_load of search.ascx  i.e
     
    Dim ctlControl As Control
    ctlControl = LoadControl("results.ascx")
    plhResults.Controls.Add(ctlControl)

    The above works fine in terms of redisplaying the results datagrid, all that I want to do is to persist the value entered into the textbox. So how can I do it?

    0
     
    LVL 28

    Expert Comment

    by:mmarinov
    BJM1M,

    so what is the problem now ? you can not page again or you can no get the value for search ?

    B..M
    0
     

    Author Comment

    by:BJM1M
    Thw problem is as stated before; the value for the search is nothing.

    Please bear with me as I may not have fully understood what you are telling me do. All I want is to retain the value entered in the search textbox between postbacks.
    0
     
    LVL 28

    Expert Comment

    by:mmarinov
    BJM1M,

    so the problem is that you lose the value for search right ?

    B..M
    0
     
    LVL 28

    Expert Comment

    by:mmarinov
    BJM1M,

    for this there is a problem with loading the user control for search
    a solution for this is when you press the search button , save the value for searching in a session variable
    then in your results page work with this variable but not with the value stored in the property srchTxt of the search user control

    B..M
    0
     

    Author Comment

    by:BJM1M
    Yes this is the problem.

    I could start a new question as you have answered the orginal question. Not a problem for me - Please advise.

    Anyway, I would welcome your help to resolve this last hurdle.
    0
     

    Author Comment

    by:BJM1M
    Is there a way to programatically retrieve the value withour resorting to session variables? Should I add the control at the Page initialisation stage?If so, do you have any examples?
    0
     
    LVL 28

    Expert Comment

    by:mmarinov
    BJM1M,

    the correct way of ask-answer question is to keep to the title of the question.
    on of the reason a care of is that if the question is resolved , when the EE members search for something they will see that this question is something they should know, but the first think that they would see will be the title and it won't be related with the search criteria

    so i would suggest you to open anew question with the exact title

    B..M
    0
     
    LVL 28

    Accepted Solution

    by:
    BJM1M,

    the best way of creating dynamically controls is to add them in the Page_Init event - this will quarantee you that the user control is added to the viewstate and it won't be necessery to recreate it every time

    B..M
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Product Review - Android Remix

    Come along for the ride with our Senior Product Manager, Brian Matis, as he reviews the Android Remix.

    It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
    International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
    With the advent of Windows 10, Microsoft is pushing a Get Windows 10 icon into the notification area (system tray) of qualifying computers. There are many reasons for wanting to remove this icon. This two-part Experts Exchange video Micro Tutorial s…
    Need more eyes on your posted question? Go ahead and follow the quick steps in this video to learn how to Request Attention to your question. *Log into your Experts Exchange account *Find the question you want to Request Attention for *Go to the e…

    846 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    6 Experts available now in Live!

    Get 1:1 Help Now