Maintain Tab index after post back - c#

I have an Order page with 4 textboxes that are inside an ajax updatepanel. All the 4 have TextChanged events. None of the controls in this page have TabIndex property set. When I enter text in textbox1 & press the tab key, it causes postback, but the next focus is not on textbox2 as I want. The focus is on the page instead. Similarly with all the textboxes.
This Order page uses a master page.
Master page:
<form id = "form1" runat="server">
<asp:ScriptManager ID="ScriptManager1 " runat="server" />
Order page:
<asp:content id ="bodycontent" contentplaceholderID="maincontent" runat="server">
// 4 text boxes
</asp:content>
I cannot add another form or scriptmanager tag in the order page as it errors out saying there can be only instance of them.
So ,there is no FormOrder or ScriptManagerOrder in the Order page's code behind, but I would like to do something of the foll. way.
How can I do this.
protected void textbox1_TextChanged(object sender, EventArgs e)
{
//someFunction();
TextBox tb = (TextBox)FormOrder.FindControl("textbox2");
ScriptManagerOrder.SetFocus(tb);
}

Try this
protected void textbox1_TextChanged(object sender, EventArgs e)
{
//someFunction();
TextBox tb = (TextBox)FormOrder.FindControl("textbox2");
tb.focus();
}

Add following script in js file called i.e focus.js:
var lastFocusedControlId = "";
function focusHandler(e) {
document.activeElement = e.originalTarget;
}
function appInit() {
if (typeof(window.addEventListener) !== "undefined") {
window.addEventListener("focus", focusHandler, true);
}
Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(pageLoadingHandler);
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoadedHandler);
}
function pageLoadingHandler(sender, args) {
lastFocusedControlId = typeof(document.activeElement) === "undefined"
? "" : document.activeElement.id;
}
function focusControl(targetControl) {
if (Sys.Browser.agent === Sys.Browser.InternetExplorer) {
var focusTarget = targetControl;
if (focusTarget && (typeof(focusTarget.contentEditable) !== "undefined")) {
oldContentEditableSetting = focusTarget.contentEditable;
focusTarget.contentEditable = false;
}
else {
focusTarget = null;
}
targetControl.focus();
if (focusTarget) {
focusTarget.contentEditable = oldContentEditableSetting;
}
}
else {
targetControl.focus();
}
}
function pageLoadedHandler(sender, args) {
if (typeof(lastFocusedControlId) !== "undefined" && lastFocusedControlId != "") {
var newFocused = $get(lastFocusedControlId);
if (newFocused) {
focusControl(newFocused);
}
}
}
Sys.Application.add_init(appInit);
Reference it using Scriptmanager like below:
<ajax:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<ajax:ScriptReference Path="~/Js/FixFocus.js" />
</Scripts>
</ajax:ScriptManager>
For more information check out below link:
http://couldbedone.blogspot.in/2007/08/restoring-lost-focus-in-update-panel.html

It's not a good practice to use server-side controls for a Tab. Why don't you use some jQuery/Bootstrap?
With your current approach you use to many useless Posts/Postbacks overloading your server with a useless work.

Related

How to find a master page list control using its id on master page iitself and add attribute to it? [duplicate]

I have a master page which contains a label for status messages. I need to set the status text from different .aspx pages. How can this be done from the content page?
public partial class Site : System.Web.UI.MasterPage
{
public string StatusNachricht
{
get
{
return lblStatus.Text;
}
set
{
lblStatus.Text = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
I have tried this, but was unsuccessful in making it work:
public partial class DatenAendern : System.Web.UI.Page
{
var master = Master as Site;
protected void Page_Load(object sender, EventArgs e)
{
if (master != null)
{
master.setStatusLabel("");
}
}
protected void grdBenutzer_RowCommand(object sender, GridViewCommandEventArgs e)
{
try
{
//some code
if (master != null)
{
master.setStatusLabel("Passwort erfolgreich geändert.");
}
}
catch (Exception ex)
{
if (master != null)
{
master.setStatusLabel("Passwort konnte nicht geändert werden!");
}
}
}
}
}
In the MasterPage.cs file add the property of Label like this:
public string ErrorMessage
{
get
{
return lblMessage.Text;
}
set
{
lblMessage.Text = value;
}
}
On your aspx page, just below the Page Directive add this:
<%# Page Title="" Language="C#" MasterPageFile="Master Path Name"..... %>
<%# MasterType VirtualPath="Master Path Name" %> // Add this
And in your codebehind(aspx.cs) page you can then easily access the Label Property and set its text as required. Like this:
this.Master.ErrorMessage = "Your Error Message here";
In Content page you can access the label and set the text such as
Here 'lblStatus' is the your master page label ID
Label lblMasterStatus = (Label)Master.FindControl("lblStatus");
lblMasterStatus.Text = "Meaasage from content page";
It Works
To find master page controls on Child page
Label lbl_UserName = this.Master.FindControl("lbl_UserName") as Label;
lbl_UserName.Text = txtUsr.Text;
I have a helper method for this in my System.Web.UI.Page class
protected T FindControlFromMaster<T>(string name) where T : Control
{
MasterPage master = this.Master;
while (master != null)
{
T control = master.FindControl(name) as T;
if (control != null)
return control;
master = master.Master;
}
return null;
}
then you can access using below code.
Label lblStatus = FindControlFromMaster<Label>("lblStatus");
if(lblStatus!=null)
lblStatus.Text = "something";
You cannot use var in a field, only on local variables.
But even this won't work:
Site master = Master as Site;
Because you cannot use this in a field and Master as Site is the same as this.Master as Site. So just initialize the field from Page_Init when the page is fully initialized and you can use this:
Site master = null;
protected void Page_Init(object sender, EventArgs e)
{
master = this.Master as Site;
}
This is more complicated if you have a nested MasterPage. You need to first find the content control that contains the nested MasterPage, and then find the control on your nested MasterPage from that.
Crucial bit: Master.Master.
See here: http://forums.asp.net/t/1059255.aspx?Nested+master+pages+and+Master+FindControl
Example:
'Find the content control
Dim ct As ContentPlaceHolder = Me.Master.Master.FindControl("cphMain")
'now find controls inside that content
Dim lbtnSave As LinkButton = ct.FindControl("lbtnSave")
If you are trying to access an html element: this is an HTML Anchor...
My nav bar has items that are not list items (<li>) but rather html anchors (<a>)
See below: (This is the site master)
<nav class="mdl-navigation">
<a class="mdl-navigation__link" href="" runat="server" id="liHome">Home</a>
<a class="mdl-navigation__link" href="" runat="server" id="liDashboard">Dashboard</a>
</nav>
Now in your code behind for another page, for mine, it's the login page...
On PageLoad() define this:
HtmlAnchor lblMasterStatus = (HtmlAnchor)Master.FindControl("liHome");
lblMasterStatus.Visible =false;
HtmlAnchor lblMasterStatus1 = (HtmlAnchor)Master.FindControl("liDashboard");
lblMasterStatus1.Visible = false;
Now we have accessed the site masters controls, and have made them invisible on the login page.

On Button Click Does Not Fire Up The PostBackUrl Once

This seems to be an easy one but got stuck on it last few hours. I've a search button that fires up PostBackUrl. The issue is it only fires up when I click the search button for the second time. Here what I did:
Default.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
Page.Title = "View Cities - CcmApp";
if (!IsPostBack)
{
BindGridView(0);
BindPager(0);
GetCountries();
}
}
protected void SearchButton_Click(object sender, EventArgs e)
{
City aCity = new City();
aCity.CityName = nameTextBox.Text;
if (nameTextBox.Text.Length == 0 && radioCityName.Checked == true)
{
labelMsg.Visible = true;
labelMsg.Text = "No search term given";
}
else
{
SearchButton.PostBackUrl = GetDefaultUrl();
}
BindGridView(0);
BindPager(0);
}
public string GetDefaultUrl()
{
return "SearchCity.aspx?SearchTerm=" + nameTextBox.Text;
}
Default.aspx:
<asp:LinkButton ID="SearchButton" runat="server" Text="Search" ValidationGroup="vdGroup"
CssClass="btn btn-primary" OnClick="SearchButton_Click"></asp:LinkButton>
I am not sure what causes it click second time to get the url. Is there any way to get over it?
Note: I am expecting to get the following output in the url -
http://localhost:1234/UI/SearchCity.aspx?SearchTerm=a. But works only on second button click. When I click for the first time, I get this - http://localhost:1234/UI/SearchCity.aspx
The PostBackUrl url on the button is only set AFTER the first PostBack. If you would set it in Page_Load for example you will see that it will work on the first PostBack.
If you want the ?SearchTerm= in the url only when there is content in nameTextBox you could use Response.Redirect or accept that there is no data in ?SearchTerm=.
Better still check on the Clientside if nameTextBox has text and prevent the button click using a Validator.
<asp:LinkButton ID="LinkButton1" runat="server" PostBackUrl="/Default.aspx?SearchTerm=" ValidationGroup="mySearch">Search</asp:LinkButton>
<asp:CustomValidator ID="CustomValidator1" runat="server" ControlToValidate="nameTextBox" ClientValidationFunction="checkLength" ValidateEmptyText="true" ErrorMessage="Min. 3 characters required" ValidationGroup="mySearch"></asp:CustomValidator>
<script type="text/javascript">
function checkLength(oSrc, args) {
var v = document.getElementById("<%=nameTextBox.ClientID %>").value;
if (v.length < 3) {
args.IsValid = false;
} else {
$("#<%=LinkButton1.ClientID %>").attr("onclick", $("#<%=LinkButton1.ClientID %>").attr("onclick").replace("?SearchTerm=", "?SearchTerm=" + v));
args.IsValid = true;
}
}
</script>

Hiding a linkbutton on the master page

I'm trying to show 2 link buttons in the master page, but these buttons should be Enable/Disable according to the content page. I already retrieve the information from the content page, and it works well, the only thing is that I can't turn enable the buttons once I have disabled them. I have tried several ways, but every attempt seems to do the same. Here is my code.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
ASPxListBox listBoxSA = new ASPxListBox();
listBoxSA = (ASPxListBox)ContentPanelHidden.FindControl("ASPxListBox2");
if (listBoxSA != null)
{
if (listBoxSA.Items.Count > 0)
{
EnableButtons(true);
}
else
{
EnableButtons(false);
}
}
}
else
{
EnableButtons(false);
}
}
public void EnableButtons(Boolean enable)
{
btnNext.Enabled = enable;
btnPrint.Enabled = enable;
}
PS. The boolean is changing its value, but the button is always disabled
I would enclose these buttons in an update panel and tell the update panel to update itself after setting the Enabled property. That should update the buttons with only a partial page update.
HTML
<asp:UpdatePanel ID="MyUpdatePanel" runat="server" UpdateMode="Conditional" ClientIDMode="Static">
<ContentTemplate>
... buttons here ...
</ContentTemplate>
</asp:UpdatePanel>
CODE BEHIND
public void EnableButtons(Boolean enable)
{
btnNext.Enabled = enable;
btnPrint.Enabled = enable;
MyUpdatePanel.Update();
}
because you are using is post back property, once it disabled you should do a post back from your current page and also listBoxSA should not be null.

OnChange Events for Dynamically rendered User Controls in ASP.NET

I have a set of User controls shown in a Page (ABC.aspx) in 5 to 6 tabs. Each of the User control has many Textboxes, Drop Downs etc.. I need to detect any user changes on any of the fields in those user controls and do some processing on Parent page (ABC.aspx) on which these user controls reside.
The User Controls are implemented as follows.
There is an XMl file for each of User controls which is read and creates controls accordingly.
The render method in ascx.cs reads this xml file and renders the UI Acordingly for that User Control.
Lets say that sample XMl for a User control is
<uigroup groupname ="Schematic(Logical) Symbol Request">
<uirow>
<uicontrol displayname="Request Type" datatype="DropDown" isrequired="false" domainname="RequestType" dropdownEventHandler="OnScenarioChange(this)" key="Schematic Scenario" defaultValue="New"></uicontrol>
</uirow>
<uirow>
<uicontrol displayname="Logical Name" datatype="TextBox" isrequired="false" supportedscenarios="New,Use Existing,Update Existing" key="Schematic Symbol Name"></uicontrol>
<uicontrol displayname="Similar Symbol" datatype="TextBox" isrequired="false" supportedscenarios="New" key="Similar Schematic Symbol"></uicontrol>
</uirow>
<uirow>
<uicontrol displayname="Type of Change" datatype="DropDown" isrequired="false" domainname="Type of Schematic Change" supportedscenarios="Update Existing" key="Type of Schematic Change"></uicontrol>
<uicontrol displayname="Layout Preference" datatype="DropDown" isrequired="false" domainname="Schematic Layout Preference" supportedscenarios="New,Update Existing" key="Schematic Layout Preference"></uicontrol>
</uirow>
<uirow>
<uicontrol displayname="Justification" datatype="DropDown" isrequired="false" domainname="Schematic Justification" supportedscenarios="Update Existing" key="Schematic Justification"></uicontrol>
<uicontrol displayname="Logical Directory" datatype="DropDown" isrequired="false" domainname="ICL Logical Directory" supportedscenarios="New" key="ICL Logical Directory"></uicontrol>
</uirow>
Usercontrol.ascx.cs has
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Page_Init(object sender, EventArgs e)
{
this.Render();
}
public void Render()
{
this.Render(this.XmlPath);
}
and my render function does the following
public void Render(string _filePath)
{
UITab tab = this.GetDataFromXML(_filePath);
foreach (UIGroup g in tab.Groups)
{
//Add a panel
Panel groupPanel = this.AddPanel(g);
foreach (UIRow r in g.Rows)
{
Table table = new Table();
groupPanel.Controls.Add(table);
TableRow tableRow = new TableRow();
table.Rows.Add(tableRow);
foreach (UIControl c in r.Controls)
{
switch (c.DataType)
{
case UIDataType.Textbox:
this.AddTextBox(groupPanel, c, tableRow);
break;
case UIDataType.Dropdown:
this.AddDropdown(groupPanel, c, tableRow);
break;
case UIDataType.LabelInfo:
this.AddLabelInfo(groupPanel, c,tableRow);
break;
case UIDataType.Label:
this.AddLabel(groupPanel, c,tableRow);
break;
}
}
}
}
}
We are rendering other user controls similar way. we need to find a way to detect user changes on any of these user controls (like a text box changed or dropdown changed etc..) and do process the Parent page.
I am not sure if Delegates and Events might be a good fit and if yes, how would they fit in this architecture are my biggest questions here. Any constructive inputs would really help.
Thanks,
Yes, creating a custom event for your UserControl makes a lot of sense.
Here's an example (note: the example shows the basic idea and does not use an XML document as a datasource; nonetheless, the example should be sufficiently instructive that you can apply it to what you've built):
Code for a simple User Control that dynamically injects nested controls:
...in the ascx file:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="TabControl.ascx.cs" Inherits="StackOverflowAspNetQuestionAnswers.Controls.TabControl" %>
<asp:Panel ID="panel" runat="server">
</asp:Panel>
...in the code-behind file for the user control:
public partial class TabControl : System.Web.UI.UserControl
{
public event EventHandler<ControlChangedEventArgs> ControlUpdated;
protected void Page_Load(object sender, EventArgs e)
{
TextBox textBox = new TextBox();
textBox.AutoPostBack = true;
textBox.ID = "textBox";
textBox.TextChanged += textBox_TextChanged;
DropDownList dropDown = new DropDownList();
dropDown.Items.Add(new ListItem("Option 1", "Option 1"));
dropDown.Items.Add(new ListItem("Option 2", "Option 2"));
dropDown.AutoPostBack = true;
dropDown.TextChanged += dropDown_TextChanged;
panel.Controls.Add(textBox);
panel.Controls.Add(dropDown);
}
void dropDown_TextChanged(object sender, EventArgs e)
{
ControlChangedEventArgs args = new ControlChangedEventArgs();
args.ControlID = ((DropDownList)sender).ID;
args.ControlValue = ((DropDownList)sender).SelectedValue;
ControlUpdated(this, args);
//CODE EDIT:
UnhookEventHandlers();
}
void textBox_TextChanged(object sender, EventArgs e)
{
ControlChangedEventArgs args = new ControlChangedEventArgs();
args.ControlID = ((TextBox)sender).ID;
args.ControlValue = ((TextBox)sender).Text;
ControlUpdated(this, args);
//CODE EDIT:
UnhookEventHandlers();
}
public virtual void OnControlUpdated(ControlChangedEventArgs e)
{
EventHandler<ControlChangedEventArgs> handler = ControlUpdated;
if (handler != null)
{
handler(this, e);
}
//CODE EDIT:
UnhookEventHandlers();
}
//CODE EDIT:
private void UnhookEventHandlers()
{
foreach (var c in panel.Controls.OfType<DropDownList>())
{
c.TextChanged -= dropDown_TextChanged;
}
foreach (var c in panel.Controls.OfType<TextBox>())
{
c.TextChanged -= textBox_TextChanged;
}
}
}
public class ControlChangedEventArgs : EventArgs
{
public string ControlID { get; set; }
public string ControlValue { get; set; }
}
Here's the code for the parent page that uses this simple tab control:
...in the .aspx file:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="RaisingEventFromUserControl_Question.aspx.cs" Inherits="StackOverflowAspNetQuestionAnswers.RaisingEventFromUserControl_Question" %>
<%# Register Src="~/Controls/TabControl.ascx" TagPrefix="uc1" TagName="TabControl" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="message" runat="server" />
<uc1:TabControl runat="server" id="TabControl" />
</div>
</form>
</body>
</html>
...in the code-behind file of the parent page:
public partial class RaisingEventFromUserControl_Question : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TabControl.ControlUpdated += TabControl_ControlUpdated;
}
void TabControl_ControlUpdated(object sender, ControlChangedEventArgs e)
{
//EDIT: add code to update some data source to lock the form from other users
message.Text = String.Format("A child control with an ID of '{0}' was updated. It now has the value of '{1}'.", e.ControlID, e.ControlValue);
}
}
As you can see in the example, I have a custom event named "ControlUpdated," which I fire anytime there is a change to either the nested TextBox or DropDownList that I dynamically inject into the UserControl at runtime. Also, keep in mind that I set the "AutoPostBack" property for both the TextBox and DropDownList to ensure that the client-side code generated by ASP.Net executes whenever I change the value of the textbox / dropdown.
Also, you can see that for my custom event, I also created a custom EventArgs class so that I could pass along pertinent information from the nested control that is updated (that is, both the ID and the changed value).

<a> tag problems and code behind problems

I got a problem, that i can't find the solution for.
Code
<a runat="server" href="#" onclick="login_box();">
<asp:Label ID="LabelLogin" runat="server" Text=""></asp:Label>
</a>
Code Behind
protected void Page_Load(object sender, EventArgs e)
{
if (Session["UserId"] == null)
{
LabelLogin.Text = "Login";
}
else
{
LabelLogin.Text = "Logud";
}
}
It's okay, but now the problem is.
That i now want this one too on the 'a' tag's onclick, but it already got an "onclick" that opens the login box, this one checks for logged in or not, and if you aren't logged in, then it should open the "onclick login_box();" and if not, then it should logout.
This is used when you click on the either "login" or "logout".
I need a solution, for how i execute "onclick login_box" in code behind. And what i should do for the clicks, is it possible that i should move "login_box" to "onclientclick" and then i can use the "onclick" ?
if (Session["UserId"] == null)
{
//Opens the login box
}
else
{
Session.Abandon();
Response.Redirect("~/default.aspx");
}
This is how you can call JavaScript function in C#
public string functionname()
{
Page page = HttpContext.Current.CurrentHandler as Page;
page.ClientScript.RegisterStartupScript(typeof(Page), "CallMyClick", "<script type='text/javascript'>login_box();</script>");
}
Accessing ASP.NET Session variable using Javascript:
<script type="text/javascript">
function LoginLogOut()
{
var userId = '<%= Session["UserId"] %>';
if(userId != undefined)
{
document.getElementById("giveIdToAnchroTag").onclick = function (){LoginFunction();};
}
else
{
document.getElementById("giveIdToAnchroTag").onclick = function (){logOutFunction();};
}
}
</script>

Categories

Resources