Gridview: how to restore page position after user clicked - asp.net

i have a gridview control on the page with 10 pages and in that gridview column i have a hyperlink where user can click the link and it will take to different page.
the mainpage.aspx with my gridview control on it:
<asp:GridView ID="gv" Width="100%" runat="server" AllowPaging="true"/>
<Columns>
<asp:TemplateField ShowHeader="true">
<ItemTemplate>
<asp:Label ID="lblTitle" runat="server" Text='<%# Eval("Title") %>' />
<asp:HyperLink id="hlView" runat="server">View Users</asp:HyperLink>
</ItemTemplate>
......................
......................
.......................
public void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
HyperLink hl = e.Row.FindControl("hlView") as HyperLink;
Customers t = e.Row.DataItem;
hl.NavigateUrl = "User.aspx?Id=" + t.Id;
..................
......................
on my User.aspx page
i have
Back To Page
my question is:
here is the scanrio i ran into and not sure how to resolve this.
let says, i am on page 7 on the mainpage.aspx and i click on the link and it will take me to user.aspx page and from the user.aspx when i click on the BAck to Page then it will take me to page but i will be landed on page 1 instead of page 7
how can i restore or maintain the page number and back to the same page where i come from?
is there a way to do that?

Session State is your friend. You can either store the result set into session along with the resultset page or you can just store the page in session and query the data.
I just cannot remember if you use page_int or preload event - one of them... It will work on page load....
As Wicked Coder said use Session["PrevPage"], fill it on page_loaded event, click event

How about you try
Go Back Page
If nothing works out you can always create a Session["PrevPage"] and store the previous page name in that session and use it when you click back. But thats not the preferred way though.
EDIT:
Using Session from aspx page.
<a href='<%=Session["PrevPage"]%>'>Back To Page</a>

Related

why a multiline textbox (inside a user control) is not holding its value after a postback?

I have a user control that have a gridview, buttons and a multi-line textbox for comments.
When the page posts back, Gridview is behaving normaly (its controls keeps their values after postback). However, the Comment textbox is always empty, no matter what I do.
protected void Page_Load(object sender, EventArgs e)
{
//This code is in the user ciontrol.
if (!IsPostBack)
{
string test = this.txtDepartmentComments.Text;
}
}
I put a break point at that line and the value is always empty. I've tried also to set the value in the code behind like:
protected void Page_Load(object sender, EventArgs e)
{
//This code is in the user ciontrol.
if (!IsPostBack)
{
this.txtDepartmentComments.Text = "Test!";
}
}
But when the page loads, the control remain empty.
Any idea why this is hapenning?
EDIT
This the ascx code (i.e. user control)
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns = "false" >
</asp:GridView>
<asp:TextBox ID="txtComments" runat="server" Columns="45" TextMode= "MultiLine"/>
<asp:Button ID="btnComplete" runat="server" Text="Completed"/>
And thid id the aspx (i.e. the parent page)
<asp:Repeater ID="rpNewHire" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<user:MyUserControl ID = "MyUserControl1" runat = "server"
DepartmentID= '<%# Eval("DepID")%>'><user:MyUserControl />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
if(!IsPostBack) is for reading values from controls after postback, you are trying to read text box value on initial load which will always be empty, remove the '!' from your condition. Also it is hard to debug your issue with out the aspx page contents, try posting the design part as well in your question.
EDIT
Your user tag is not well formatted inside repeater, it is missing closing tag and runat attribute
<user:MyUserControl runat="server" ID = "MyUserControl1" DepartmentID= '<%# Eval("DepID")%>'></user:MyUserControl>
Controls inside repeater cannot be accessed directly, you have to loop through the rows of the repeater and find your child controls and then try reading values from them, that after you bind some data to the repeater.
Check this http://msdn.microsoft.com/en-us/magazine/cc163780.aspx
Page's IsPostBack and each user controls' IsPostBack are not same.
When a user control is posted back, that particular control's IsPostBack is true, but other user controls' IsPostBack are still false.
You can use explicitly !Page.IsPostBack inside a user control to check whether its parent page is posted back or not.
if(!Page.IsPostBack){
// do something
}
Dynamically Loaded Control can not maintain values at PostBack? It is not directly related to your question, but it might be useful for you.

Why do my dynamically added controls loose their values after Postback?

To ask my question I have created an aspx file containing a Button and a DataList with an SqlDataSource:
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
<asp:DataList ID="DataList1" runat="server" DataKeyField="a"
DataSourceID="SqlDataSource1" >
<ItemTemplate>
a:
<asp:Label ID="aLabel" runat="server" Text='<%# Eval("a") %>' />
<br />
b:
<asp:Label ID="bLabel" runat="server" Text='<%# Eval("b") %>' />
<br />
</ItemTemplate>
</asp:DataList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:probaConnectionString %>"
SelectCommand="SELECT [a], [b] FROM [PROBA_TABLE]"></asp:SqlDataSource>
In my code behind I add TextBoxes to the Items of the DataList. I add to every Item a TextBox in the Page_Load, and another TextBox in the Button Click eventhandler as well.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
foreach (DataListItem item in DataList1.Items)
{
item.Controls.Add(new TextBox());
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
foreach (DataListItem item in DataList1.Items)
{
item.Controls.Add(new TextBox());
}
}
}
}
This works fine except one thing. When I click the Button, the TextBoxes which were created in the Page_Load keep their Text value, but the TextBoxes which were created in the Button1_Click lose their Text values. My real problem is more complicated than this, but I think solving this would help me a lot.
Each control that should receive data from page ViewState should be instantiated in Init or Load event handlers, because ViewState is persisted to controls BEFORE Click, Change and the rest control events (those events are triggered when ViewState changes are detected, so ViewState must be read before Click event is fired).
So the process should look like:
OnInit (static controls get created)
Static control content is deserialized from ViewState
OnLoad (create dynamic controls, in your case textboxes that you created in last Postback)
Dynamic control content is deserialized from ViewState
Click, Change and other events are fired according to changes detected comparing POST data and ViewState data
Suggestions:
You can use hidden fields to save additional status information, and then in OnLoad you can read that info to recreate dynamically created controls.
Also, you should explicitly set ID property of your textboxes so that values can be properly persisted back, don't rely on ASP.Net.
the http by default is stateless that means after your request is processed the server keeps no data or info of the request
but the values in the form need to be persisted in special cases when there is an error
suppose you fill up a long form and then post it back to the server only to get an error message and all the filled up values are gone. wouldn't that be annoying
so what asp.net does behind the scenes that it keeps a string in the page hidden that has information about all the server controls and their ids
so when you post a form back the Page class is created and the values that are posted back and binded in the specific controls because the Page class is being created in every request the pageLoad event is run and controls created in the PageLoad are then present values corresponding to their ids are put into them unlike the controls that are being created on button click till the button_click event is run that viewstate has already been deseralized and values are filled into them

Load specific part in webpage?

See below image first.
we have one sidebar navigation(ajax accordion control asp.net)
now when ever user click on link inside side bar related page(content) should display in Content goes here region.
As per given instruction entire page should not be refreshed or in other word in Back Button should not work(In Internet Explorer).
what should be the way to achieve this functionality?
what should be the best suggestion for that?
EDIT: navigation tree is inside MasterPage and Content goes region is in side content page of master page
please suggest me.....
thank you so much....
The Easiest way is to Wrap your side navigation & the Content placeholder in an UpdatePanel. Set the TreeView in the side bar as the UpdateTrigger for the update Panel. But, this approach is a little inefficient.
A slightly better way is ti just wrap the Content Placeholder in an Update Panel, along with a HiddenField in it. Upon a selection in the sidebar, update the HiddenField Value with JavaScript and then refresh the update Panel.
According to:
As per given instruction entire page should not be refreshed or in other word in Back Button should not work(In Internet Explorer).
And
sidebar tree view is in master page and Content goes here region is content page
If my understanding is correct, I think you do not need to place your TreeView control in your master page because you only want one page loading dynamically the content based on the selection of your tree view. So...Why is this important? Well if you place your tree view in your page you can use an UpdatePanel to avoid full posts.
Output of the following code
The following code covers the next points:
A TreeView control is embedded in a UserControl and placed in an ASPX page (left side)
The menu contorl exposes an event that is raised whenever the selected node changes, this event is handled in the ASPX page to dynamically load user controls depending on the user selection on the right side of the page, only one content is loaded at a time.
The controls are embedded in an UpdatePanel therefore you won't change your page and your back button in your browser won't be affected
Note: the user controls keep their state across post backs
(I'm not sure if this is the best way to do it, perhaps you could try to find a solution using only ajax, and avoid the use of the evil updata panels, but certainly this is a way to do it)
I'll try to simplify the code to reduce the size of the post, I will just post the code of one user control, the other one is exactly the same I just changed its title to difference them on the page
ASCX Menu
<asp:TreeView ID="TreeView1" runat="server" onselectednodechanged="Unnamed2_SelectedNodeChanged">
<Nodes>
<asp:TreeNode Text="link1" />
<asp:TreeNode Text="link2" />
</Nodes>
<SelectedNodeStyle Font-Bold="True" Font-Italic="True" />
</asp:TreeView>
ASCX Menu code behind
public event Action<string> MenuChanged = delegate { };
protected void Unnamed2_SelectedNodeChanged(object sender, EventArgs e)
{
this.MenuChanged(this.TreeView1.SelectedNode.Text);
}
ASPX
<asp:ScriptManager runat="server" ID="sm" />
<asp:UpdatePanel runat="server" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:HiddenField runat="server" ID="currentControl" />
<table border="0" cellpadding="0" cellspacing="0" width="90%" align="center">
<tr>
<td style="width:50%; background-color: Silver">
<menu:TreeViewMenu runat="server" ID="myTreeViewMenu" OnMenuChanged="myTreeViewMenu_MenuChanged" />
</td>
<td style="width:50%; background-color: Aqua">
<p>Result:</p>
<asp:Panel runat="server" ID="myPanel">
</asp:Panel>
<asp:Label ID="lblMessage" runat="server" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
ASPX code behind
protected void Page_Init(object sender, EventArgs e)
{
if (this.IsPostBack)
{
var cc = this.Request.Form["currentControl"];
if (!string.IsNullOrWhiteSpace(cc))
{
var uc = this.LoadControl(this.Server.HtmlDecode(cc));
this.myPanel.Controls.Add(uc);
}
}
}
protected void myTreeViewMenu_MenuChanged(string e)
{
this.myPanel.Controls.Clear();
switch (e)
{
case "link1":
var cc1 = "~/Content1.ascx";
this.currentControl.Value = this.Server.HtmlEncode(cc1);
var uc1 = this.LoadControl(cc1);
this.myPanel.Controls.Add(uc1);
this.lblMessage.Text = "Updated from: link1";
break;
case "link2":
var cc2 = "~/Content2.ascx";
this.currentControl.Value = this.Server.HtmlEncode(cc2);
var uc2 = this.LoadControl(cc2);
this.myPanel.Controls.Add(uc2);
this.lblMessage.Text = "Updated from: link2";
break;
default:
this.lblMessage.Text = "Updated from default: " + e;
break;
}
}
ASCX
<h1>Content 1</h1>
<asp:TextBox runat="server" ID="txt" />
<asp:Button Text="Process data..." runat="server" OnClick="button_Click" />
<asp:Button Text="Just post" runat="server" />
<asp:Label ID="lblMessage" runat="server" />
ASCX Code Behind
protected void button_Click(object sender, EventArgs e)
{
this.lblMessage.Text = this.txt.Text;
}
You can simply copy-paste this code to test it yourself, this should work
Jupaol's answer works fine but 1 thing need to mention, I came across the problem after implemented Jupaol's idea, the first time I called the user control immediately after I click menu, the button with in the ascx works fine, but if I switch to 2nd one, first click of the button on the 2nd control will not fire on first click, this is because we do not have a "static" ID of the control. It took me almost 3 days to finally figure out why this is happening. so here's part of my code to make. I'm leaving this message in hope that anyone who read this afterwards will make the use of it.
if (!string.IsNullOrEmpty(controlPath))
{
PlaceHolder1.Controls.Clear();
UserControl uc = (UserControl)LoadControl(controlPath);
/**note below LastLoadedControl is anything that could
* be unique to the called control so every time when call back
* it will not confuse the back end so the first fire of eg. a button
* on that loaded control will work
*/
uc.ID = LastLoadedControl;
PlaceHolder1.Controls.Add(uc);
}
I'll also need to thank Jupaol's great contribution so that I can get my site running.

Link button in Repeater control redirect to grid view

I am developing a web application where I have a repeater control. A link button is inside the repeater control. When the link button is clicked, I want it to redirect to a page which would be a data entry page for that particular user(which was clicked). It has to use the user-id/emplid and pre-populate some fields in the new page and other fields should be allowed for data-entry.
My question-
How should I redirect to the new data entry page? I haven't decided on the page yet. I am thinking that it would be a form page or grid view and would be a separate page.
Code:
<asp:LinkButton ID="getDetails" OnCommand="getDetails_cmd" runat="server"
CommandArgument='<%#DataBinder.Eval(Container.DataItem,"Emplid")%>
' Text='<%#DataBinder.Eval(Container.DataItem,"NAME")%>'
CommandName="Details"></asp:LinkButton>
After redirecting to the page, I guess, using the commandargument, I can get the emplid. an I pass multiple values? Say the keys for the page?
How should I update multiple tables in the page?
Any help would be really appreciated.
Thanks,
You need handle ItemCommand event of Repeater control.
<asp:Repeater ID="Repeater1" runat="server"
onitemcommand="Repeater1_ItemCommand">
<ItemTemplate>
<asp:LinkButton
ID="getDetails"
runat="server"
Text='<%# Eval("NAME") %>'
CommandName="cmd"
CommandArgument='<%# Eval("Empid") %>'
>
</asp:LinkButton>
</ItemTemplate>
</asp:Repeater>
Handler of ItemCommand event,
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "cmd")
{
Session["empid"]=e.CommandArgument;
Response.Redirect("~/page1.aspx");
}
}
If you're trying to direct to a new page, linkbutton is probably not the way to go since it does a postback to the same form normally, a standard hyperlink sending emplid in the querystring would work. In the new page get the emplid from the querystring using Request.Querystring("emplid"). As for saving to multiple tables, there are a number of ways to do that, one would be to wrap the multiple db update calls in a transactionscope.

asp.net listbox problem

foreach (Book b in o.list)
{
ListBox_Items.Items.Add(b.Title);
}
After I do this, the titles are now showing up in the listbox.
When I make a selection (Single Mode), ListBox_Items (Screen) is highlighting the row selected, but event SelectedIndexChanged is not triggering.
protected void ListBox_Items_SelectedIndexChanged(object sender, EventArgs e)
{
int i = ListBox_Items.SelectedIndex;
}
ID="ListBox_Items" runat="server" EnableViewState="False" Width="400px" Rows="25" onselectedindexchanged="ListBox_Items_SelectedIndexChanged"
Any ideas ?
Michael
Edit 1 : Thanks to everyone for helping out. Got it to work now. Anyway, I had to turn on EnableViewState to True too. Because I have a "Remove" button to remove items from the listbox control, if EnableViewState is False, whenever I clicked the Remove button, the listbox becomes empty again.
Add AutoPostBack="True" in your aspx tag
Try the following code.
<asp:ListBox ID="ListBox_Items"
runat="server"
EnableViewState="False"
Width="400px"
Rows="25"
OnSelectedIndexChanged="ListBox_Items_SelectedIndexChanged"
AutoPostBack="true"></asp:ListBox>
Do you have anything to make the page post back to the server?
You may need either a submit button, or you can add the property AutoPostBack="true" to your ListBox control.
See this MSDN Article for more information.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.autopostback.aspx

Resources