Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

ASP.NET Problem, GridView nested within LoginView

Options
  • 28-07-2010 4:53pm
    #1
    Closed Accounts Posts: 585 ✭✭✭


    Hi Folks,

    I have a GridView1 which works fine when it is not nested within a LoginView. Basically what happens is the if the user is authenticated, the UserID Provider User Key is used to return a set of records from my mssql DB for that particular user. So in order for that part of the solution to work, I have to use a LoginView, also I only want users that are logged in to be able to see their records.

    This all works fine. The problem arises when I want to get a pop up screen to activate when a row is selected in my GridView1. It appears that when the GridView1 is nested within a LoginView, the GridView1 below cannot be referenced within the codebehind page, it seems to not exist. For example, I've set up a Label on my page (Label1), and when I try to assign the value of RowIndex to the label, I get a compilation error saying that GridView1 does not exist in this context although I can clearly see it in my aspx page. I've also made sure the GridView control is set up in my aspx.designer.cs page...

    /// <summary>
    /// GridView1 control.
    /// </summary>
    /// <remarks>
    /// Auto-generated field.
    /// To modify move field declaration from designer file to code-behind file.
    /// </remarks>
    protected global::System.Web.UI.WebControls.GridView GridView1;

    public void GridView1_SelectedIndexChanged(object sender, EventArgs e)

    {

    //Anything I put in here that starts with GridView1 seems to cause a compilation error, such as:

    GridView1.SelectedRow.RowIndex.ToString();
    }

    If I can get it to compile by putting the code above into my aspx.designer.cs page (the application keeps removing it on me!), I then get a null exception reference error for the GridView1 line above...

    Basically I'm trying to get a pop up window to open up when the user clicks a Linkbutton in my GridView that is databound to the ID column in my table... The LinkButton is working fine, it's just when the row is selected in my GridView that I'm running into a brick wall.


Comments

  • Registered Users Posts: 2,791 ✭✭✭John_Mc


    I'm confused as to why you're putting the Gridview in the LoginView? Would it not make more sense to redirect the user to a secure page after successfully signing in, and to have the Gridview located there? This is how it usually works.

    The login control is particularly clunky and will only give you headaches.


  • Closed Accounts Posts: 5,019 ✭✭✭ct5amr2ig1nfhp


    I'd agree with John_Mc, however I'm sure you could use FindControl? I'm a bit rusty but in vb it'd be something like...

    Dim gvw As GridView
    gvw = CType(Me.LoginView1.FindControl("GridView1"), GridView)


  • Closed Accounts Posts: 585 ✭✭✭MrDarcy


    John_Mc wrote: »
    I'm confused as to why you're putting the Gridview in the LoginView? Would it not make more sense to redirect the user to a secure page after successfully signing in, and to have the Gridview located there? This is how it usually works.

    The login control is particularly clunky and will only give you headaches.

    Hi Folks,

    Well I thought the way I was meant to go about it in terms of best practive was to use the LoggedInTemplate to display stuff that authethicated users could see (in this case a GridView of their recent transactions), and the AnonymousTemplate to display a Login Box.

    The idea being that using the code below controls the data that is handled in my DataSource... A user logs in, and their transactional data is presented within the GridView, this works fine and I think I need it to work this way.

    protected void SqlDataSource1_Selecting(object sender, SqlDataSourceSelectingEventArgs e)
    {

    MembershipUser currentUser = Membership.GetUser();
    Guid currentUserId = (Guid)currentUser.ProviderUserKey;
    e.Command.Parameters["@userID&quot;].Value = currentUserId.ToString();
    }




    The transctional data returned is different for every user, so that's why I thought I had to use a LoginView to do this, given that I'm using the built in membership API to secure the site...??? If there is another way of doing it though, I'll give it a shot...


  • Registered Users Posts: 180 ✭✭Collumbo


    by any chance, is GridView1 sitting inside a MasterPage?

    if so, when you are running it and the page loads, view the source html.

    is the object called gridview1? (I think it gets rendered as a table, and the Id will be GridView1).

    With a masterpage, has the name in your server side code will be changed to something like "ctl00$ContentPlaceHolder1$GridView1". I can't remember the exact naming convention used by asp.net but I'm pretty close. If you debug through your code, look at all of the child objects of the page. It will appear under some other control I'm sure...

    The other option as suggested above is to do this:
    GridView yourGridVariableName = this.Master.FindControl("GridView1") as GridView;

    aside from why you're putting it inside the LoginView (which is something i would weird to maintain in future, let alone explain to someone else who might have to look after the website), i actually don't like using GridView. You have way more control over defining a Repeater Control and I've always found them nicer to work with. Or, if we are talking about a very small piece of data, you can always write your own html output with the correct link.


  • Closed Accounts Posts: 585 ✭✭✭MrDarcy


    I'd agree with John_Mc, however I'm sure you could use FindControl? I'm a bit rusty but in vb it'd be something like...

    Dim gvw As GridView
    gvw = CType(Me.LoginView1.FindControl("GridView1"), GridView)

    Hi KingAmbrose, I've tried using the C# equivilent of your code:

    GridView gvw = default(GridView);
    gvw = (GridView)this.LoginView1.FindControl("GridView1");

    I'm still getting a null exception reference error for the GridView1 control when I select a row in the GridView after the page has loaded.

    Collumbo wrote: »
    by any chance, is GridView1 sitting inside a MasterPage?

    if so, when you are running it and the page loads, view the source html.

    is the object called gridview1? (I think it gets rendered as a table, and the Id will be GridView1).

    With a masterpage, has the name in your server side code will be changed to something like "ctl00$ContentPlaceHolder1$GridView1". I can't remember the exact naming convention used by asp.net but I'm pretty close. If you debug through your code, look at all of the child objects of the page. It will appear under some other control I'm sure...

    The other option as suggested above is to do this:
    GridView yourGridVariableName = this.Master.FindControl("GridView1") as GridView;

    aside from why you're putting it inside the LoginView (which is something i would weird to maintain in future, let alone explain to someone else who might have to look after the website), i actually don't like using GridView. You have way more control over defining a Repeater Control and I've always found them nicer to work with. Or, if we are talking about a very small piece of data, you can always write your own html output with the correct link.

    Hi Collumbo, I'm using a MasterPage but the GridView is not in the MasterPage but is in an aspx page called ViewTransaction.aspx.

    No matter what I do here, I seem to be getting a null reference exception error... :confused::confused::confused:

    EDIT: I'm not a big time asp.net developer, I just need to get the functionality in place for a site launch for my own business and I developed the site myself. I thought this was the best way to do it and I'm very happy with the presentation of the data once I can select a row on the datagrid and open up a window to show more data for that record I'm laughing! I'm 99% of the way there so if I can push this over the line I'd be delighted!


  • Advertisement
  • Closed Accounts Posts: 585 ✭✭✭MrDarcy


    OK I think I'm starting to get somewhere...

    using the code below:

    GridView gvw = default(GridView);
    gvw = (GridView)this.LoginView1.FindControl("GridView1");
    string TempString = gvw.ToString();
    Label1.Text = TempString.ToString();

    Within the public void GridView1_SelectedIndexChanged event handler, I now get the text:

    System.Web.UI.WebControls.GridView

    Displayed on my webpage where I have my label1 control...

    When I change the code above to the code below though, I get Object reference not set to an instance of an object.


    GridView gvw = default(GridView);
    gvw = (GridView)this.LoginView1.FindControl("GridView1");
    string TempString = GridView1.SelectedValue.ToString();
    Label1.Text = TempString.ToString();


  • Registered Users Posts: 339 ✭✭duffman85


    When you say that you are selecting a row, do you mean that you are clicking the linkbutton on a particular row.

    If that's the case you want to use the RowCommand Event which is raised when a button in the gridview button is clicked.
    Here's sample code from Microsoft MSDN for ASP .NET 3.5.

    Full details are here: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowcommand.aspx
    <%@ Page language="C#" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <script runat="server">
    
      void ContactsGridView_RowCommand(Object sender, GridViewCommandEventArgs e)
      {
        // If multiple buttons are used in a GridView control, use the
        // CommandName property to determine which button was clicked.
        if(e.CommandName=="Add")
        {
          // Convert the row index stored in the CommandArgument
          // property to an Integer.
          int index = Convert.ToInt32(e.CommandArgument);
    
          // Retrieve the row that contains the button clicked 
          // by the user from the Rows collection.
          GridViewRow row = ContactsGridView.Rows[index];
    
          // Create a new ListItem object for the contact in the row.     
          ListItem item = new ListItem();
          item.Text = Server.HtmlDecode(row.Cells[2].Text) + " " +
            Server.HtmlDecode(row.Cells[3].Text);
    
          // If the contact is not already in the ListBox, add the ListItem 
          // object to the Items collection of the ListBox control. 
          if (!ContactsListBox.Items.Contains(item))
          {
            ContactsListBox.Items.Add(item);
          }
        }
      }    
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
      <head runat="server">
        <title>GridView RowCommand Example</title>
    </head>
    <body>
        <form id="form1" runat="server">
    
          <h3>GridView RowCommand Example</h3>
    
          <table width="100%">
            <tr>
              <td style="width:50%">
    
                <asp:gridview id="ContactsGridView" 
                  datasourceid="ContactsSource"
                  allowpaging="true" 
                  autogeneratecolumns="false"
                  onrowcommand="ContactsGridView_RowCommand"
                  runat="server">
    
                  <columns>
                    <asp:buttonfield buttontype="Link" 
                      commandname="Add" 
                      text="Add"/>
                    <asp:boundfield datafield="ContactID" 
                      headertext="Contact ID"/>
                    <asp:boundfield datafield="FirstName" 
                      headertext="First Name"/> 
                    <asp:boundfield datafield="LastName" 
                      headertext="Last Name"/>
                  </columns>
    
                </asp:gridview>
    
              </td>
    
              <td style="vertical-align:top; width:50%">
    
                Contacts: <br/>
                <asp:listbox id="ContactsListBox"
                  runat="server" Height="200px" Width="200px"/>
    
              </td>
            </tr>
          </table>
    
          <!-- This example uses Microsoft SQL Server and connects    -->
          <!-- to the AdventureWorks sample database. Use an ASP.NET  -->
          <!-- expression to retrieve the connection string value     -->
          <!-- from the Web.config file.                              -->
          <asp:sqldatasource id="ContactsSource"
            selectcommand="Select [ContactID], [FirstName], [LastName] From Person.Contact"
            connectionstring="<%$ ConnectionStrings:AdventureWorks_DataConnectionString%>" 
            runat="server"/>
    
        </form>
      </body>
    </html>
    
    
    
    


  • Closed Accounts Posts: 585 ✭✭✭MrDarcy


    Hi DuffMan, this is exactly what I'm trying to do, I've dropped a LinkButton into the left column of my GridView. I've bound it to the ID column of my DB table, so a user can see their transaction ID in the LinkButton text.

    What I want is when the LinkButton is clicked, a new pop window appears which is basically a detailed invoice for that particular row.

    Obviously the next step is to pass the ID value onto the new window that I have opening up. The problem is my LoginView is a must have as far as I can see...


  • Closed Accounts Posts: 585 ✭✭✭MrDarcy


    Just an update, I've taken the LoginView out of my page and I'm dealing with user states programatically and all is fine now, thanks to everyone above for advice with this...

    What I'm doing though is opening up a child window on:

    public void GridView1_SelectedIndexChanged(object sender, EventArgs e)
    {

    string strScript = "<script>";
    strScript += "var newWindow = window.open('newpage.aspx', '_blank','height=450, center:yes, width=450, status=no, resizable= yes, menubar=no, toolbar=no, location=yes, scrollbars=no, status=no');";
    strScript += "</script>";
    ClientScript.RegisterClientScriptBlock(this.GetType(), "clientScript", strScript);
    string PassID = GridView1.SelectedValue.ToString();
    Label1.Text = GridView1.SelectedValue.ToSTring();


    }


    This code opens up a new child window when a new row in my GridView is selected and sets the value of string PassID to the ID of the respective row in my mssql DB. I've assigned the value of GridView1.SelectedValue.ToSTring();, to my label1 control to check that the right ID is being returned and this is the case...

    All I need to ask now is how do I pass this value from the parent page with the GridView, to the Child page with more detailed info for the same mssql ID value that has been passed to it via my passID string on the parent page???


  • Registered Users Posts: 2,791 ✭✭✭John_Mc


    MrDarcy wrote: »
    Just an update, I've taken the LoginView out of my page and I'm dealing with user states programatically and all is fine now, thanks to everyone above for advice with this...

    What I'm doing though is opening up a child window on:

    public void GridView1_SelectedIndexChanged(object sender, EventArgs e)
    {

    string strScript = "<script>";
    strScript += "var newWindow = window.open('newpage.aspx', '_blank','height=450, center:yes, width=450, status=no, resizable= yes, menubar=no, toolbar=no, location=yes, scrollbars=no, status=no');";
    strScript += "</script>";
    ClientScript.RegisterClientScriptBlock(this.GetType(), "clientScript", strScript);
    string PassID = GridView1.SelectedValue.ToString();
    Label1.Text = GridView1.SelectedValue.ToSTring();


    }


    This code opens up a new child window when a new row in my GridView is selected and sets the value of string PassID to the ID of the respective row in my mssql DB. I've assigned the value of GridView1.SelectedValue.ToSTring();, to my label1 control to check that the right ID is being returned and this is the case...

    All I need to ask now is how do I pass this value from the parent page with the GridView, to the Child page with more detailed info for the same mssql ID value that has been passed to it via my passID string on the parent page???

    You're doing this wrong, although getting it out of that Login control was a good start!

    As someone above pointed out, the Gridview control has a RowCommand event. When you click the button, the row command event is fired and you receive the selected row in the form of an GridViewCommandEventArgs. You can access the properties of this object to identify the row that was selected, and then use that to access the column of that selected row.

    From the MSDN page linked above:
    void ContactsGridView_RowCommand(Object sender, GridViewCommandEventArgs e)
      {
        // If multiple buttons are used in a GridView control, use the
        // CommandName property to determine which button was clicked.
        if(e.CommandName=="Add")
        {
          // Convert the row index stored in the CommandArgument
          // property to an Integer.
          int index = Convert.ToInt32(e.CommandArgument);
    
          // Retrieve the row that contains the button clicked 
          // by the user from the Rows collection.
          GridViewRow row = ContactsGridView.Rows[index];
    
          // Create a new ListItem object for the contact in the row.     
          ListItem item = new ListItem();
          item.Text = Server.HtmlDecode(row.Cells[2].Text) + " " +
            Server.HtmlDecode(row.Cells[3].Text);
    
          // If the contact is not already in the ListBox, add the ListItem 
          // object to the Items collection of the ListBox control. 
          if (!ContactsListBox.Items.Contains(item))
          {
            ContactsListBox.Items.Add(item);
          }
        }
      }    
    

    In your Gridview, add the following:

    onrowcommand="ContactsGridView_RowCommand"

    In answer to your question about passing it to a new page. You can do this a few ways, and which way you go with depends on the type of data - is it private/sensitive etc

    You can pass it to the new page through a Querystring value. E.g Newpage.aspx?PageId=6

    You can store it in session memory and then access it on the new page.

    Unless it's sensitive information, I'd recommend the former. Working with session variables can get very messy very easily...


  • Advertisement
  • Closed Accounts Posts: 585 ✭✭✭MrDarcy


    Hi John, as it is at the moment, it's working. The only reason I'm sticking with handling the event through:

    public void GridView1_SelectedIndexChanged(object sender, EventArgs e)

    Is because I have it set up so that when the row is selected, it is highlighted on the screen and if I revert back to using the RowCommand event to handle the new window, the row is no longer highlighted in the browser. As it is at the moment, I get my ID back in a string that I need to the parent page Label, I get the row highlighted which seems to be a result, AND I get the new window opened up! I've hardcoded in a DetailsView controls on my new page, and they are bound to a DataSource.

    All I need to do now is get the DataSource to select rows from my DB where the ID value equals the ID string passed from the parent page to the child page... I'm trying to do it using the Newpage.aspx?PageId=6 approach, but I need to change:

    string strScript = "<script>";
    strScript += "var newWindow = window.open('newpage.aspx','NewPage', '_blank','height=450, center:yes, width=450, status=no, resizable= yes, menubar=no, toolbar=no, location=yes, scrollbars=no, status=no');";
    strScript += "</script>";

    ... To take account of the variable...


  • Registered Users Posts: 2,791 ✭✭✭John_Mc


    string pageUrl = "Newpage.aspx?PageId=" + PassId;

    Or you could use the string.format function: string pageUrl=string.format("Newpage.aspx?PageId={0}",PassId);

    Personally, I think you should avoid using a popup window as these are blocked by most modern browsers. Why not have a user control situated underneath the Grid which is invisible unless something is selected?


  • Closed Accounts Posts: 585 ✭✭✭MrDarcy


    John_Mc wrote: »
    string pageUrl = "Newpage.aspx?PageId=" + PassId;

    Or you could use the string.format function: string pageUrl=string.format("Newpage.aspx?PageId={0}",PassId);

    Personally, I think you should avoid using a popup window as these are blocked by most modern browsers. Why not have a user control situated underneath the Grid which is invisible unless something is selected?

    Thanks for that John.

    Yeah I hear you on the pop up windows being blocked, this is just an inhouse solution for printing invoices and barcode labels, I think I'll take your advice on that and put the DetailsView below the GridVew for customers of the site who are tracking their orders via their own browsers...

    Don't I have to put a QueryString or or something like that into the child page to basically "grab" the value being passed and put it into a local variable or something like that???


  • Registered Users Posts: 2,791 ✭✭✭John_Mc


    MrDarcy wrote: »
    Thanks for that John.

    Don't I have to put a QueryString or or something like that into the child page to basically "grab" the value being passed and put it into a local variable or something like that???

    Yes, you can access the Querystring value like this:

    if(Request.Querystring["PageId"]!=null)
    {
    pageId = Request.Querystring["PageId]".ToString();
    }

    Always ensure it's not null before trying to use ToString on it or you'll get a null reference exception.


  • Closed Accounts Posts: 585 ✭✭✭MrDarcy


    Got the exact result I was took for, thank's to everyone on the thead for their help again...

    EDIT: Just discovered an obvious flaw with this, which is that if the DB record in question that is referenced by it's ID, contains personal information (which it does, delivery name, contact num, email, etc), I can't use this approach for displaying invoice to customers because they can just use the URL and add in any an ID number at the end of it, and basically start rooting through transactions that are for other people so sounds like I'll have to use your idea John of doing it all on the same page...


Advertisement