Load specific part in webpage? - asp.net

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.

Related

How to set focus back to control that originated postback

To avoid unwarranted "duplicate" flagging, let me say upfront - I have searched high and low for an answer and only found ones like this, which has no answer, or this, which tells me to use MyControl.Focus(); from my code behind. That does not work properly. I will explain.
I have a series of dropdown controls in an update panel, each of which affects the ones after it - City, Building and Room. When the user changes the selection in the city dropdown, mouse or keyboard, focus is immediately lost as the page does the partial postback. Ok, so I try to put in the CityListDropDown.Focus();, but that causes the page to reposition itself so that this control is at the bottom of the visible area of the page - not the desired behavior. The page should not move at all. Mind you, this only matters if you have a lot of other stuff on the page before your update panel, so that these prompts are lower down where the page has had to scroll down to them.
So, how do I restore focus back to that city drop down so when the user is using the keyboard, they can just keep on trucking to the next prompt? Same goes for the building drop down.
Here is my html:
<asp:UpdatePanel ID="RoomsUpdatePanel" runat="server" UpdateMode="Conditional" RenderMode="Inline">
<ContentTemplate>
<asp:DropDownList ID="CityListDropDown" runat="server" class="form-control input-sm" Width="140" AutoPostBack="True" OnSelectedIndexChanged="CityListDropDown_SelectedIndexChanged">
</asp:DropDownList>
<asp:DropDownList ID="BuildingListDropDown" runat="server" class="form-control input-sm" AutoPostBack="True" Width="100" OnSelectedIndexChanged="BuildingListDropDown_SelectedIndexChanged">
</asp:DropDownList>
<asp:DropDownList ID="RoomListDropDown" runat="server" class="form-control input-sm" AutoPostBack="False" Width="175">
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
and here is my code behind:
protected void CityListDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
LoadBuildingList();
LoadRoomList();
CityListDropDown.Focus();
}
protected void BuildingListDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
LoadRoomList();
BuildingListDropDown.Focus();
}
If you don't want the page to scroll / get repositioned whenever the focus is changed, you can use the PageMaintainScrollPositionOnPostback property of the Page directive :
<%# PageMaintainScrollPositionOnPostback="true" ... %>
or you can try setting it programatically through code :
Page.MaintainScrollPositionOnPostBack = true;
I got it! So using the code behind Focus() method of the control causes the page to reposition itself, even when you have set the MaintainScrollPositionOnPostBack property of the page to true. But, javascript can change focus without moving the page around unnecessarily. So if I need to reset focus from my code behind, to the sending control, I can do this:
protected void CityListDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
LoadBuildingList();
LoadRoomList();
ScriptManager.RegisterStartupScript(CityListDropDown, CityListDropDown.GetType(), "CityDropDownRefocus", "document.getElementById(\"" + CityListDropDown.ClientID + "\").focus();", true);
}
or, if I want that line of code that resets the focus to be more generic (say I have an event handler that is used by multiple controls, and I need the handler to reset focus to the control that generated the postback, the handler is going to get the sending object, so I can say:
protected void MyControlHandler(object sender, EventArgs e)
{
...
ScriptManager.RegisterStartupScript((WebControl)sender, sender.GetType(), "CityDropDownRefocus", "document.getElementById(\"" + ((WebControl)sender).ClientID + "\").focus();", true);
}
And that resets the focus back to the sending control, without moving the page around!

asp.net set textbox control in panel contol

I want to set the textbox contol located in the panel control via code
I know to retrieve the inputted value in the textbox control:
string myVal = Request.Form["txtResult"];
I want to set the txtResult.text = "some text";
makeup snippet:
<asp:Panel ID="Panel1" runat="server" Style="display: none" Width="233px">
<asp:TextBox ID="txtResult" runat="server" AutoPostBack="True"></asp:TextBox>
<br />
<div align="center">
<asp:Button ID="OkButton" runat="server" Text="OK" />
<asp:Button ID="CancelButton" runat="server" Text="Cancel" />
</div>
</asp:Panel>
txtResult is not available within code, I tried to see if it is available in the page_load, it's not
texReults was a typo, its txtResult, I updated the ID
the intellisense does not recognize any cntr by the name txtResult
its a new web application and the panel visibility=True
maybee this wil help, above the snipet, I use ScriptManager from the AJAX Exstension
I am aware of he Asnchronius affects, partial potback, etc.
It's a managed control, you should be able to set it on the Page_Load event:
protected void Page_Load(object sender, System.EventArgs e)
{
txtResult.Text = "some text";
}
Update: Based on your update, there are a couple of things that you would need to check:
Spelling: Are you sure you're spelling the control name correctly?
Its ID in your code is "txtResults", but you're referencing it as
"txtResult".
Designer: Did you copy the aspx page or bypass VS in some way for this page? If so check the .designer file for the reference to the control: i.e. "Page1.aspx.designer.cs"
Visibility: Is the Panel control's visibility set to true? If not, then it won't render the controls that are contained within it.
Update 2: If you're doing this through scriptmanager, then I highly recommend that you read through this: http://www.wrox.com/WileyCDA/Section/Using-the-ASP-NET-AJAX-ScriptManager.id-305492.html

lazy loading asp.net Ajax Control Toolkit accordion

I am using the asp.net Ajax Control Toolkit accordion (http://www.asp.net/ajaxlibrary/act_Accordion.ashx) and each accordion pane contains quite a lof information.
All that info is generated in the page but it is not shown because the toolkit gives the non active panes a
(style="display:none;)
But because the info is in the page, it becomes a very heavy page to load.
I am looking for a way to load the panes on-demand: so only if the user clicks the pane an ajax request is send and the pane is loaded and expanded.
Can this be done with this control or should i choose a different accordion? Any help or suggestions appreciated.
update
Currently the Accordion is created with two, nested, repeaters. The first repeater loops over the categories and creates a panel for each category. The second repeater repeates inside each panel takes the content for one category and creates the content of the panel.
Pleun
I don't have the points to comment and ask you questions. Sorry. :(
My questions are in regard to how you plan to create and populate the Accordion.
Will you create panes by hand using markup in the IDE or will you bind the Accordion to a DataSource that will dynamically create the panes you need?
Will you have 3 separate DataSources or a different combination of the following:
1.) DataSource to initialize the number of panels and populate only the panel's Header information.
2.) DataSource to populate the Static Content of all panels on first load.
3.) DataSource to populate the Lazy-Loaded Content of a single panel the user clicks to expand.
With your answers I hope to update this answer with a real one. Thanks.
Update: This is achievable with the Ajax Control Toolkit's Accordion.
I have some very basic code below as proof of concept. It could be smoother, but I'll leave it up to you to add a "Loading" image using the UpdatingProgress control if you find it necessary.
The Accordion in the Aspx markup:
(Notice the UpdatePanels - you can replace them with callbacks if you want, I just wanted to keep the answer simple)
<asp:Accordion ID="acc_Accordion" runat="server" RequireOpenedPane="false"
SelectedIndex="-1" onitemcommand="acc_Accordion_ItemCommand" >
<HeaderTemplate>
<asp:UpdatePanel ID="up_UpdateHeader" runat="server">
<ContentTemplate>
<%--When using "Eval" inside strings for Asp.net controls,
you MUST wrap them in apostrophes ('),
otherwise with (") you will get parser errors!--%>
<asp:LinkButton ID="btn_Header" runat="server"
Text='<%# Eval("HeaderText") %>'
CommandName="UpdatePane" CommandArgument='<%# Eval("ItemID") %>'
Font-Underline="false" ForeColor="Black"
style="width:100%; height:100%; cursor:pointer;"/>
<%--Use Cursor:Pointer to keep a consistent
interface after disabling the button.--%>
</ContentTemplate>
</asp:UpdatePanel>
</HeaderTemplate>
<ContentTemplate>
<asp:UpdatePanel ID="up_UpdateContent" runat="server"
UpdateMode="Conditional">
<ContentTemplate>
<%# Eval("ContentText")%>
<asp:Label ID="lbl_Content" runat="server"
Text="<%# DateTime.Now.ToLongTimeString() %>"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
</ContentTemplate>
</asp:Accordion>
The Page_Load() - Prep our "dummy" data:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
DataTable dt = new DataTable();
dt.Columns.Add("ItemID");
dt.Columns.Add("HeaderText");
dt.Columns.Add("ContentText");
dt.Rows.Add(new object[] { 123456, "Header 1", "Content A." });
dt.Rows.Add(new object[] { 654321, "Header 2", "Content B." });
acc_Accordion.DataSource = new System.Data.DataTableReader(dt);
acc_Accordion.DataBind();
}
}
The ItemCommand() - This captures button-clicks inside the Accordion:
protected void acc_Accordion_ItemCommand(object sender, CommandEventArgs e)
{
if (e.CommandName == "UpdatePane")
{
AjaxControlToolkit.AccordionContentPanel acp
= (e as AjaxControlToolkit.AccordionCommandEventArgs).Container;
UpdatePanel upHeader
= acc_Accordion.Panes[acp.DisplayIndex].HeaderContainer
.Controls.OfType<Control>()
.Single(c => c is UpdatePanel) as UpdatePanel;
LinkButton btn
= upHeader.ContentTemplateContainer
.Controls.OfType<Control>()
.Single(b => b is LinkButton) as LinkButton;
UpdatePanel upContent
= acc_Accordion.Panes[acp.DisplayIndex].ContentContainer
.Controls.OfType<Control>()
.Single(c => c is UpdatePanel) as UpdatePanel;
Label lbl
= upContent.ContentTemplateContainer
.Controls.OfType<Control>()
.Single(c => c is Label) as Label;
lbl.Text = " ID: " + e.CommandArgument
+ " and Time: " + DateTime.Now.ToLongTimeString();
//You can use the ID from e.CommandArgument to query the database
// for data to update your Repeaters with.
btn.Enabled = false;//Disabling the button for our Header
// will prevent Asyncronous Postbacks to update the content again.
//Only disable this if you don't need to update the content
// when the user clicks to view the pane again.
upContent.Update();//Set UpdateMode="Conditional".
}
}
I know this looks like a lot, but it's only a few lines of code (before wrapping and commenting).
Tip 4 in 6 Tips for Working with the ASP.NET AJAX Accordion Control explains how to determine when the selected index has changed. From the JavaScript event handler you can do whatever you want to update the content of the newly-selected accordion pane (call a web service, use an update panel, etc.)
Combining this with another article explaining how to use an update panel to refesh content when a tab page is selected for a simple demo:
<ajaxToolKit:Accordion ID="accSample" runat="server"
RequireOpenedPane="false" SelectedIndex="-1">
<Panes>
<ajaxToolKit:AccordionPane runat="server">
<Header>Sample</Header>
<Content>
<asp:Button ID="btnSample" runat="server" OnClick="OnShowSample" Style="display: none" />
<script type="text/javascript">
Sys.Application.add_load(function (sender, args) {
if (!args.get_isPartialLoad()) {
var accSample = $find('<%= accSample.ClientID %>_AccordionExtender');
accSample.add_selectedIndexChanged(function (sender, eventArgs) {
$get('<%= btnSample.ClientID %>').click();
});
}
});
</script>
<asp:UpdatePanel ID="upSample" runat="server">
<ContentTemplate>
<asp:DataGrid ID="dgSample" runat="server" Visible="false"/>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnSample" />
</Triggers>
</asp:UpdatePanel>
</Content>
</ajaxToolKit:AccordionPane>
</Panes>
</ajaxToolKit:Accordion>
then in code-behind
protected void OnShowSample(object sender, EventArgs e)
{
dgSample.DataSource = new string[] { "test" };
dgSample.DataBind();
dgSample.Visible = true;
}
Take a look at the ASPxNavBar control (a part of the free ASPxperience Suite) from DevExpress. If the ASPxNavBar’s EnableCallBacks property is set to true, contents of collapsed groups are not represented on the client side. When a group is expanded for the first time, its content is retrieved from the server and then cached on the client. The next time the group is expanded, its content is taken from the client and no callback to the server is performed.
Review the ASPxNavBar - Callbacks (AJAX) Online Demo for more information.
All I can suggest to you is add linkButtons to your headers and panels to your panes:
<Panes>
<asp:AccordionPane ID="First" runat="server">
<Header>
<asp:LinkButton CommandName="ASD2" ID="LinkButton2" runat="server">LinkButton</asp:LinkButton>
</Header>
<Content>
<asp:Panel ID="Panel2" runat="server" Visible="true">
First
</asp:Panel>
</Content>
</asp:AccordionPane>
<asp:AccordionPane ID="Second" runat="server">
<Header>
<asp:LinkButton CommandName="ASD" ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
</Header>
<Content>
<asp:Panel ID="Panel1" runat="server" Visible="false">
Second
</asp:Panel>
</Content>
</asp:AccordionPane>
</Panes>
and in the Accordion1_ItemCommand set the Visible property of corresponding panel.
protected void Accordion1_ItemCommand(object sender, CommandEventArgs e)

Why aren't all controls initialised at the event handling point of the ASP.NET page lifecycle?

I have a user control embedded in a web part. It has the following snippets of code:
protected TextBox searchTextBox;
protected Button goButton;
protected Button nextButton;
protected Repeater pushpins;
protected Label currentPageLabel;
protected void goButton_Click(object sender, EventArgs e)
{
// Do stuff
}
<asp:TextBox ID="searchTextBox" runat="server" />
<asp:Button ID="goButton" runat="server" Text="Go" OnClick="goButton_Click" />
<asp:Repeater ID="pushpins" runat="server" EnableViewState="false">
<ItemTemplate>Blah</ItemTemplate>
</asp:Repeater>
<asp:Label ID="currentPageLabel" runat="server" />
<asp:Button ID="nextButton" runat="server" Text=" >> " OnClick="nextButton_Click" />
(There is no OnLoad or CreateChildControls method.)
If I place a breakpoint on the first line of goButton_Click, I find:
searchTextBox: initialised
goButton: initialised
nextButton: NULL
pushpins: initialised
currentPageLabel: NULL
Why are some controls initialised and others not? How do I get around this if I'd like to update the Text property on currentPageLabel?
Update:
I've placed breakpoints all the way through the page life cycle and found that nextButton and currentPageLabel are never initialised. The breakpoints were placed at OnLoad, CreateChildControls, goButton_Click, OnPreRender, Render and OnUnload.
Is it possible you've inadvertently got local variables named currentPageLabel and/or nextButton declared somewhere? The compiler will happily allow this...
This is especially common in a move from ASP.NET 1.1 to 2.0 or higher, since the way the designer defined these controls changed.
The problem was that all of the controls that weren't being initialised were inside a HeaderTemplate within a Repeater control. (To save space I didn't paste all of my code into the question, dang it.)
I moved them out and the problem is resolved. Obviously controls in the HeaderTemplate are instantiated by the Repeater and do not follow the normal page life cycle.

multiple forms in asp.net

is it possible to display, with a click of a button an entirely different form on the same aspx page? please take note that although i have experience with vb.net, i have almost none with asp.net. thank you very much for your responses
I would use and in your code behind, load up the page and then place it in the placeHolder. And then hide the old form using javascript. The idea the other person said would also work, but I like using the placeholder, myself.
I think it's all really determinate on what you want to do with the forms and how badly you would want the code for the other form laying on the page, or not.
If I understand, what you need is, on the click event:
response.redirect "newpage.aspx"
Create each of the forms on the same page, one with visible=true and the other visible=false, and when the user clicks on the appropriate button, switch the visibilities.
<form id="Form1" runat="server" visible="true">
<div>
<asp:Button ID="Button1" runat="server" Text="Show Form 2" onclick="Button1_Click" />
</div>
</form>
<form id="Form2" runat="server" visible="false">
<div>
<asp:Button ID="Button2" runat="server" Text="Show Form 1" onclick="Button2_Click" />
</div>
</form>
And in the code behind:
protected void Button1_Click(object sender, EventArgs e)
{
this.form2.Visible = true;
this.form1.Visible = false;
}
protected void Button2_Click(object sender, EventArgs e)
{
this.form2.Visible = false;
this.form1.Visible = true;
}
Probably not the most "Ajaxy" solution, but you could use an iframe, with the src set to the forms location.
You should be aware of ASP.NET's MultiView control. It does require a postback to change views, and it is kinda heavy on the ViewState, but its an option to consider.
Well, there's several ways to go about that I suppose. Riffing off tekBlues, you can do a Server.Transfer "yourpage.aspx". You can then use the PreviousPage property to get to data from the old page.
You can use user controls and a placeholder on the main page. Of course dynamically loaded controls holds extra complexity.
You could use a MultiView control. Asp.Net will maintain all vars for you. Useful for the quick and dirty.
These are all webform solutions though. If you're looking for an AJAX solution, might need to keep on looking for answers.
It is NOT allowed to have more then 1 form runat="server" on an asp.net page. What you could do, is create 2 panels on your page, 1 with the Visible property set to false. Then when a button is clicked in the event handler you set the Visisble property to true, while setting the other 1 to false. Wrap the Panel in an UpdatePanel to get rid of the postback.
<asp:UpdatePanel><ContentTemplate>
<asp:Panel ID="pnl1" runat="server">
<asp:Button OnClick="Button_CLick" />
</asp:Panel>
<asp:Panel ID="pnl2" runat="server" Visible="false">
</asp:Panel></ContentTemplate></asp:UpdatePanel>
the code in the Button_CLick handler would then be pnl1.Visible = false; pnl2.Visible = true;
You could do it with CSS/Javascript, here is what I would do first:
1) code up two forms, place them in a separate divs
2) using CSS hide one div on page load
3) then place a button on the page, in the onlick button event unhide the second form and hide the first one.
Make sure that you only have ONE form tag, but 2 divs inside it which you will hide/unhide. Keep in Mind that that the form can only be submitted to its own page, that's asp.net.
in your HTML:
<form runat="server" id="myForm">
<div id="myForm1">
<! -- form 1 code goes here -- !>
</div>
<div id="myForm2">
<! -- form 2 code goes here -- !>
</div>
<input type="button" onclick="toggleVisibility();" />
</form>
Then in your CSS
#myForm1 {
display: none;
}
Then ToggleVisibility() will change the display attribute of divs.
Use AJAX to load the content of another page into the same page.
Use Response.Redirect or Server.Transfer to move to the next page.

Resources