Master.cs running after the page content codebehind - c#

I have an issue where I am setting session variables using the master page, then using those session variables to deal with content in my placeholder. However, the session variables are not showing as updated in the content. I've made a small example below.
I need the session variables to be updated in both the masterpage and the content. Right now, it's as if the content codebehind is running either before or simultaneous with the masterpage. I assumed that the masterpage codebehind would run first, thus setting the session variables. Any help would be greatly appreciated. Thanks! (.NET 2.0 build using C#)
testmass.master
<%# Master Language="C#" inherits="gpworklist.testmass"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head runat="server">
</head>
<body>
<form id="testthisform">
<select id="test1sel" name="test1" runat="server"></select>
<select id="test2sel" name="test2" runat="server"></select>
<input type="submit" value="Submit" />
</form>
<div id="testsess" runat="server"></div>
<asp:ContentPlaceHolder id="cntnt_phldr" runat="server">
</asp:ContentPlaceHolder>
</body>
</html>
testmass.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.Web.UI.WebControls;
namespace gpworklist
{
public class testmass: MasterPage
{
public string defProv;
public testmass()
{
}
public void Page_Load()
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
Response.Cache.SetExpires(DateTime.MinValue);
HtmlSelect sel1 = (HtmlSelect)this.FindControl("ctl00$test1sel");
HtmlSelect sel2 = (HtmlSelect)this.FindControl("ctl00$test2sel");
HtmlGenericControl div = (HtmlGenericControl)this.FindControl("ctl00$testsess");
string def1;
string def2;
ListItem item;
if (Request["ctl00$test1sel"] != null && Request["ctl00$test1sel"] != "")
{
Session["test1"] = Request["ctl00$test1sel"];
}
if (Request["ctl00$test2sel"] != null && Request["ctl00$test2sel"] != "")
{
Session["test2"] = Request["ctl00$test2sel"];
}
if (Session["test1"] != null)
{
def1 = Session["test1"].ToString();
}
else
{
def1 = "";
}
if (Session["test2"] != null)
{
def2 = Session["test2"].ToString();
}
else
{
def2 = "";
}
for (int i = 0; i <= 10; i++)
{
item = new ListItem(i.ToString(), i.ToString());
if (i.ToString() == def1)
{
item.Selected = true;
}
sel1.Items.Add(item);
}
//Session["test1"] = sel1.Value;
for (int i = 0; i <= 10; i++)
{
item = new ListItem(i.ToString(), i.ToString());
if (i.ToString() == def2)
{
item.Selected = true;
}
sel2.Items.Add(item);
}
Session["test2"] = sel2.Value;
div.InnerHtml = Session["test1"] + " - " + Session["test2"];
}
}
}
testpage.aspx
<%# Page Language="C#" MasterPageFile="testmass.master" Inherits="gpworklist.testpage"%>
<asp:content ID="contentstuff" contentplaceholderid="cntnt_phldr" runat="server">
<div id="testpagesess" runat="server"></div>
</asp:content>
testpage.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.Web.UI.WebControls;
namespace gpworklist
{
public class testpage: Page
{
public testpage()
{
}
public void Page_Load()
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
Response.Cache.SetExpires(DateTime.MinValue);
HtmlGenericControl div = (HtmlGenericControl)this.FindControl("ctl00$cntnt_phldr$testpagesess");
div.InnerHtml = Session["test1"] + " - " + Session["test2"];
}
}
}

A content page's event does fire before the same master page's event.
see http://msdn.microsoft.com/en-us/library/vstudio/dct97kc3(v=vs.100).aspx

You should use the Init event of the MasterPage, instead of the Load event. That will be called before the Page.Load.

Related

How to display a google bar chart, instead of data table only?

This is asp.net coding website page coding page in here I insert the JavaScript and retrieve data by ID just I set height and weight only
<h1 class="style2"> Channeling Paid and UnPaid Monthly</h1>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<asp:GridView ID="Ch_Data_Monthly" runat="server" BackColor="White"
BorderColor="#3366CC" BorderStyle="None" BorderWidth="1px" CellPadding="4">
</asp:GridView>
<asp:Literal ID="ltScriptsDataMonthly" runat="server"></asp:Literal>
<div id="Ch_BarChart_Monthly" style="width: 900px; height: 300px;" />
This is the C# coding. I'm getting data by SQL Server R2 stored procedure.
i have connecting my data bases by web config called "connectionString"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Configuration;
using System.Text;
using System.Data;
using System.Web.Security;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Monthly Bind Gridview
Bind_Ch_Data_Monthly();
// Monthly Bind Charts
BindChart_Monthly();
}
}
//Monthly Channeling Paid and UnPaid
private void Bind_Ch_Data_Monthly()
{
Ch_Data_Monthly.DataSource = GetChartDataMonthly();
Ch_Data_Monthly.DataBind();
}
private void BindChart_Monthly()
{
DataTable dsChartDataMonthly = new DataTable();
StringBuilder strScriptDataMonthly = new StringBuilder();
try
{
dsChartDataMonthly = GetChartDataMonthly();
strScriptDataMonthly.Append(#"<script type='text/javascript'>
google.charts.load('visualization', '1', {packages: ['bar']});
google.charts.setOnLoadCallback(drawChart);</script>
<script type='text/javascript'>
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Months', 'Paid', 'UnPaid'],");
foreach (DataRow row in dsChartDataMonthly.Rows)
{
strScriptDataMonthly.Append("['" + row["Months"] + "'," + row["Paid"] + "," + row["UnPaid"] + "],");
}
strScriptDataMonthly.Remove(strScriptDataMonthly.Length - 1, 1);
strScriptDataMonthly.Append("]);");
strScriptDataMonthly.Append("var options = {chart: {title: 'Company Performance',subtitle: 'Sales, Expenses, and Profit: 2014-2017',}};");
strScriptDataMonthly.Append("var chart = new google.charts.Bar(document.getElementById(document.getElementById('Ch_BarChart_Monthly')); chart.draw(data, options); } google.setOnLoadCallback(drawChart)");
strScriptDataMonthly.Append(" </script>");
ltScriptsDataMonthly.Text = strScriptDataMonthly.ToString();
}
catch
{
}
finally
{
dsChartDataMonthly.Dispose();
strScriptDataMonthly.Clear();
}
}
/// <summary>
/// fetch data from mdf file saved in app_data
/// </summary>
/// <returns>DataTable</returns>
private DataTable GetChartDataMonthly()
{
DataSet dsData = new DataSet();
try
{
SqlConnection sqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString);
SqlDataAdapter sqlCmd = new SqlDataAdapter("DSB_Ch_MonthWise_Paid&UnPaid", sqlCon);
sqlCmd.SelectCommand.CommandType = CommandType.StoredProcedure;
sqlCon.Open();
sqlCmd.Fill(dsData);
sqlCon.Close();
}
catch
{
throw;
}
return dsData.Tables[0];
}
}
only need one document.getElementById
replace this...
var chart = new google.charts.Bar(document.getElementById(document.getElementById('Ch_BarChart_Monthly')); chart.draw(data, options); } google.setOnLoadCallback(drawChart)
with this...
var chart = new google.charts.Bar(document.getElementById('Ch_BarChart_Monthly')); chart.draw(data, options); } google.setOnLoadCallback(drawChart);
Please fix this line and try
document.getElementById(document.getElementById('Ch_BarChart_Monthly'))
Try this
document.getElementById('Ch_BarChart_Monthly'));
chart.draw(data, options);
google.setOnLoadCallback(drawChart)

Scriptmanager equaivalent required in converting webform to mvc

Basically I have a webform with a scriptmanager and a button to update the results returned from the class webspider (web spider that searches for broken links for a given url). I am trying to convert the code to mvc and have achieved most of this except for the code that is highlighted in bold as I do not have a scriptmanager in the mvc view, can some please give me some pointers on how I can do this, many thanks. -
default.aspx -
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="_check404._Default" %>
<asp:Content runat="server" ID="FeaturedContent" ContentPlaceHolderID="FeaturedContent">
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1><%: Title %>.</h1>
<h2>Modify this template to jump-start your ASP.NET application.</h2>
</hgroup>
<p>
To learn more about ASP.NET, visit http://asp.net.
The page features <mark>videos, tutorials, and samples</mark> to help you get the most from ASP.NET.
If you have any questions about ASP.NET visit
our forums.
</p>
</div>
</section>
</asp:Content>
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
<h3>Search results:</h3>
<asp:Label ID="lblTot" runat="server" />
<asp:Label runat="server" ID="lblStatus" />
<asp:UpdatePanel runat="server" ID="pnlLinks">
<ContentTemplate> -->
<asp:GridView runat="server" ID="grvLinks" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="NavigateUrl" HeaderText="Url" />
<asp:ButtonField DataTextField="Status" HeaderText="Status" />
</Columns>
</asp:GridView>
<asp:Button runat="server" ID="btnUpdateResults" Text="Update Results" />
</ContentTemplate>
</asp:UpdatePanel>
default.aspx.cs -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using _check404.Spider;
using System.Net;
namespace _check404
{
public partial class _Default : Page
{
private string script = #"setTimeout(""__doPostBack('{0}','')"", 5000);";
private WebSpider WebSpider
{
get { return (WebSpider)(Session["webSpider"] ?? (Session["webSpider"] = new WebSpider())); }
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!this.WebSpider.IsRunning)
{
string url = "http://bbc.co.uk";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
this.WebSpider.Execute(url);
lblTot.Text = WebSpider.Tot.ToString();
}
//////////////////////////the following code is what I am trying to convert
if (this.WebSpider.IsRunning)
{
this.lblStatus.Text = "Processing...";
ScriptManager.RegisterStartupScript(this, this.GetType(),
this.GetType().Name, string.Format(script, this.btnUpdateResults.ClientID), true);
}
///////////////////////////////////////////////////////////////////////////////////////
this.grvLinks.DataSource = this.WebSpider.Links;
this.grvLinks.DataBind();
}
}
}
spider.cs -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
namespace _check404.Spider
{
public class WebSpider
{
public int Tot { get; set; }
const int LIMIT = 10;
string[] invalidTypes = { ".zip", ".doc", ".css", ".pdf", ".xls", ".txt", ".js", ".ico" };
public List<Link> Links;
public bool IsRunning { get; set; }
public WebSpider()
{
this.Links = new List<Link>();
}
public void Execute(string url)
{
this.Links.Clear();
this.Links.Add(new Link() { Status = HttpStatusCode.OK, NavigateUrl = url });
this.IsRunning = true;
WaitCallback item = delegate(object state) { this.FindLinks((UrlState)state); };
ThreadPool.QueueUserWorkItem(item, new UrlState() { Url = url, Level = 0 });
Tot = Links.Count();
}
public void FindLinks(UrlState state)
{
try
{
string html = new WebClient().DownloadString(state.Url);
MatchCollection matches = Regex.Matches(html, "href[ ]*=[ ]*['|\"][^\"'\r\n]*['|\"]");
foreach (Match match in matches)
{
string value = match.Value;
value = Regex.Replace(value, "(href[ ]*=[ ]*')|(href[ ]*=[ ]*\")", string.Empty);
if (value.EndsWith("\"") || value.EndsWith("'"))
value = value.Remove(value.Length - 1, 1);
if (!Regex.Match(value, #"\((.*)\)").Success)
{
if (!value.Contains("http:"))
{
Uri baseUri = new Uri(state.Url);
Uri absoluteUri = new Uri(baseUri, value);
value = absoluteUri.ToString();
}
if (this.Links.Exists(x => x.NavigateUrl.Equals(value))) continue;
try
{
bool validLink = true;
foreach (string invalidType in invalidTypes)
{
string v = value.ToLower();
if (v.EndsWith(invalidType) || v.Contains(string.Format("{0}?", invalidType)))
{
validLink = false;
break;
}
}
if (validLink)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(value);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
this.Links.Add(new Link() { Status = response.StatusCode, NavigateUrl = value });
if (response.StatusCode == HttpStatusCode.OK && state.Level < LIMIT)
{
WaitCallback item = delegate(object s) { FindLinks((UrlState)s); };
ThreadPool.QueueUserWorkItem(
item, new UrlState() { Url = value, Level = state.Level + 1 });
}
}
}
catch
{
this.Links.Add(new Link()
{
Status = HttpStatusCode.ExpectationFailed,
NavigateUrl = value
});
}
}
}
}
catch
{
///
/// If downloading times out, just ignore...
///
}
}
}
}
It looks like you are trying to automatically click a button after 5 seconds if the your spider job is running.
All the script manager is doing is embedding a tag containing your javascript when the markup is generated.
Id say the easiest way to do this is to add an attribute to your model.
class MyModel
{
public bool SpiderRunning { get; set; }
}
Then set this in your controller:
model.SpiderRunning = this.WebSpider.IsRunning
Then in your view, only add the script to the page if this value is true:
#if(Model.SpiderRunning)
{
<script>setTimeout(function(){document.getElementById("btnUpdateResults").click();}, 5000);</script>
}

ASP.NET page crashes with MySql connection

I am trying to write a dashboard with information about the website's hits and where people come from etc.
I wrote the following page:
<%# Page Language="C#" Inherits="Daschboard.Board" MasterPageFile="~/site.master" %>
<asp:Content id="main" runat="server" ContentPlaceHolderID="main">
<asp:UpdatePanel runat="server" id="updateableWidgets">
<ContentTemplate>
<asp:ContentPlaceHolder id="WidgetsTable">
</asp:ContentPlaceHolder>
</ContentTemplate>
</asp:UpdatePanel>
</asp:Content>
With the following code behind:
using Widgets;
using System;
using System.Text;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Configuration;
using MySql.Data.MySqlClient;
namespace Daschboard
{
public partial class Board : System.Web.UI.Page
{
protected List<IWidget> widgets;
private MySqlConnection db = new MySqlConnection (ConfigurationManager.AppSettings ["mySql"]);
protected void Page_Load(object sender, EventArgs e)
{
widgets = new List<IWidget>();
BuildWidgtTable();
var WidgetThread = new System.Threading.Thread(new System.Threading.ThreadStart(this.InitWidgets));
WidgetThread.Start();
}
private string BuildWidgtTable ()
{
StringBuilder sb = new StringBuilder ();
db.Open ();
var tableName = ConfigurationManager.AppSettings ["DatabaseSiteName"];
var query = "SELECT * FROM " + tableName + ", Widget WHERE " + tableName + ".WidgetID = Widget.WidgetID";
var command = new MySqlCommand (query, db);
var result = command.ExecuteReader ();
while (result.Read()) {
widgets.Add(getWidget(result.GetString(4)));
}
db.Close ();
sb.Append("<table>\n");
sb.Append("</table>");
result.Close();
return sb.ToString();
}
private void InitWidgets ()
{
db.Open();
foreach (var widget in widgets) {
var siteId = ConfigurationManager.AppSettings["siteID"];
var query = "SELECT * FROM Values, Widget WHERE Widget.WidgetID = Values.WidgetID AND SiteID = " + siteId;
var command = new MySqlCommand(query, db);
var result = command.ExecuteReader();
while(result.Read()){
Console.WriteLine(result);
}
result.Close();
widget.Init ("1");
}
db.Close();
}
private IWidget getWidget (string fileName)
{
IWidget widget = null;
switch (fileName) {
case "PageHits":
widget = new PageHits();
break;
case "SiteHits":
widget = new SiteHits();
break;
}
return widget;
}
}
}
When I run this something goes wrong; the debugger stops working without a good error.
It does load the widgets from the database but it doesn't get the values from the database.
I am using Monodevelop on a Mac.
You are running the widget initialization method in a separate thread (InitWidgets method). The page might have already finished rendering when this method executes. If you want to use asynchronous operations in ASP.NET I would recommend you reading about Asynchronous Pages on MSDN. The idea is to mark your WebForm as asynchronous by setting Async="true" in your Page directive (<%# Page Async="true" ... %>) and then use the RegisterAsyncTask method on your web form.

The report you requested requires further information with crystal report2008,vs2008

i am having problem in crystal report.i am sending you my .aspx page and codebehind page.Thing is that with the same code which i sending its working good in vs2005,windowsxp.But just now we moved into window7 and i am creating another one now its not woking.
Please suggest me.
.aspx code:-
<%# Page Language="C#" AutoEventWireup="true" Culture="en-AU" CodeFile="report1.aspx.cs" Inherits="report1" %>
<%# Register Assembly="CrystalDecisions.Web,Version=10.5.3700.0,Culture=neutral,PublicKeyToken=692fbea5521e1304"
Namespace="CrystalDecisions.Web" TagPrefix="CR" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Jumbo Bags Report Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<CR:CrystalReportViewer ID="CrystalReportViewer1"
runat="server"
AutoDataBind="True"
Height="1116px"
ReportSourceID="CrystalReportSource1"
Width="887px" DisplayGroupTree="False" />
<CR:CrystalReportSource ID="CrystalReportSource1" runat="server">
<Report FileName="CR_rpt1.rpt">
</Report>
</CR:CrystalReportSource>
</div></form>
</body></html>
codebehind page:-
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using JumboBagsApp.Library;
public partial class report1 : System.Web.UI.Page
{
private void setDBLOGONforREPORT(ConnectionInfo myconnectioninfo)
{
TableLogOnInfos mytableloginfos = new TableLogOnInfos();
mytableloginfos = CrystalReportViewer1.LogOnInfo;
foreach (TableLogOnInfo myTableLogOnInfo in mytableloginfos)
{
myTableLogOnInfo.ConnectionInfo = myconnectioninfo;
}
}
protected void Page_Load(object sender, EventArgs e)
ConnectionInfo myConnectionInfo = new ConnectionInfo();
myConnectionInfo.ServerName = "xxxxxxxx";
myConnectionInfo.DatabaseName = "xxxxx";
myConnectionInfo.UserID = "xxx";
myConnectionInfo.Password = "xxxxxxx";
myConnectionInfo.Type = ConnectionInfoType.SQL;
myConnectionInfo.IntegratedSecurity = false;
setDBLOGONforREPORT(myConnectionInfo);
ReportDocument reportDocument = new ReportDocument();
ParameterField paramField = new ParameterField();
ParameterFields paramFields = new ParameterFields();
ParameterDiscreteValue paramDiscreteValue = new ParameterDiscreteValue();
string scompany = "";
string sempcode = "";
string ssr_no = "";
string sappln_no = "";
if (Request.QueryString["comcode"] != null && Request.QueryString["comcode"].ToString() != "")
{
scompany = Request.QueryString["comcode"].ToString();
}
if (Request.QueryString["empcode"] != null && Request.QueryString["empcode"].ToString() != "")
{
sempcode = Request.QueryString["empcode"].ToString();
}
//DateTime dtSysdate4 = DateTime.Parse(txtfrom_date2.Text, CultureInfo.CreateSpecificCulture("en-AU"), DateTimeStyles.AssumeLocal);
//string txtdate4 = dtSysdate3.ToString("yyyy/MM/dd");
//string strcur_date4 = txtdate4;
if (Request.QueryString["cur_date"] != null && Request.QueryString["cur_date"].ToString() != "")
{
sappln_no = Request.QueryString["cur_date"].ToString();
}
Library lib = new Library();
//library lib = new library();
DataTable dtdetailed = new DataTable();
//dtdetailed = lib.GetDetaileddbySrno(sappln_no.Trim());
if (sappln_no != "")
{
paramField = new ParameterField();
paramField.Name = "#cur_date";
paramDiscreteValue = new ParameterDiscreteValue();
paramDiscreteValue.Value = sappln_no.Trim();
paramField.CurrentValues.Add(paramDiscreteValue);
paramFields.Add(paramField);
CrystalReportViewer1.ParameterFieldInfo = paramFields;
CrystalReportViewer1.RefreshReport;
}
else
{
Response.Write("SrNo Not Found");
return;
}
}
}
Please suggest me.
thanks.
DisplayGroupTree property is obsolete for CrystalReportViewer in VS 2008. delete it.
you can use ToolPanelView property et set to ToolPanelViewType.GroupTree or ToolPanelViewType.ParameterPanel.

ASP.NET Client Id's not being generated for loaded control

I have a UserControl ('AddressInfoGroup') within an updatepanel that dynamically loads user controls ('AddressInfo') via the loadControl method. I have two other such controls on the same page, both of which function correctly.
When the AddressInfoGroup control renders an AddressInfo control to the page, the text boxes in AddressInfo have id's unchanged from the ascx markup. These id's should have been dynamically generated by the .NET clientID process. Because of this, when a second AddressInfo control is added to AddressInfoGroup, I get a runtime exception "An entry with the same key already exists". The two working controls produce proper clientID's and consequently don't return this error.
I should also mention that the AddressInfoGroup control has a few buttons which are correctly rendered with clientID so it seems to be an issue with the AddressInfo control itself. Any suggestions at all would be really helpful!
AddressInfoGroup markup
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="AddressInfoGroup.ascx.cs" Inherits="MFRI.Controls.Contact.AddressInfoGroup" %>
<h2>Address information</h2>
<div class="formGroup">
<asp:PlaceHolder ID="plc_infoCtrls" runat="server" />
<asp:Button id="btn_addAddress" CssClass="btn_add" Text="v" runat="server" OnClick="addAddress_click" UseSubmitBehavior="false" CausesValidation="false" />
<asp:Button id="btn_removeAddress" CssClass="btn_remove" Text="^" runat="server" OnClick="removeAddress_click" UseSubmitBehavior="false" CausesValidation="false" />
</div>
AddressInfoGroup codebehind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MFRI.Common.Contact;
using MFRI.Common;
namespace MFRI.Controls.Contact
{
public partial class AddressInfoGroup : System.Web.UI.UserControl
{
private int _maxNumberOfControls = 3;
private int _minNumberOfControls = 1;
private List<Address> _controlListToBind = null;
public int NumberOfControls
{
get { return SafeConvert.ToInt(ViewState["NumberOfControls"] ?? 0); }
set { ViewState["NumberOfControls"] = value; }
}
public bool Editable
{
get { return (bool)(ViewState["InfoControlsEditable"] ?? false); }
set { ViewState["InfoControlsEditable"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (_controlListToBind != null && _controlListToBind.Count > 0)
{
NumberOfControls = _controlListToBind.Count;
foreach (Address address in _controlListToBind)
{
AddressInfo addressInfo = (AddressInfo)LoadControl("AddressInfo.ascx");
addressInfo.InitControl(Editable, address);
plc_infoCtrls.Controls.Add(addressInfo);
}
}
else
{
if (NumberOfControls <= 0)
NumberOfControls = 1;
for (int i = 0; i < NumberOfControls; i++)
{
AddressInfo addressInfo = (AddressInfo)LoadControl("AddressInfo.ascx");
addressInfo.InitControl(Editable, null);
plc_infoCtrls.Controls.Add(addressInfo);
}
}
RefreshButtons();
}
public void BindAddressList(List<Address> addressList)
{
_controlListToBind = addressList;
}
public List<Address> GetAddressList()
{
List<Address> returnList = new List<Address>();
foreach (AddressInfo addressInfo in plc_infoCtrls.Controls.OfType<AddressInfo>())
{
returnList.Add(addressInfo.GetAddress());
}
return returnList;
}
private void RefreshButtons()
{
btn_addAddress.Enabled = false;
btn_removeAddress.Enabled = false;
if (Editable)
{
if (NumberOfControls > _minNumberOfControls)
btn_removeAddress.Enabled = true;
if (NumberOfControls < _maxNumberOfControls)
btn_addAddress.Enabled = true;
}
}
protected void addAddress_click(object sender, EventArgs e)
{
if (NumberOfControls < _maxNumberOfControls)
{
AddressInfo addressInfo = (AddressInfo)LoadControl("AddressInfo.ascx");
addressInfo.InitControl(Editable, null);
plc_infoCtrls.Controls.Add(addressInfo);
NumberOfControls++;
}
RefreshButtons();
}
protected void removeAddress_click(object sender, EventArgs e)
{
if (_minNumberOfControls < NumberOfControls)
{
plc_infoCtrls.Controls.RemoveAt(plc_infoCtrls.Controls.Count - 1);
NumberOfControls--;
}
RefreshButtons();
}
}
}
AddressInfo markup
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="AddressInfo.ascx.cs" Inherits="MFRI.Controls.Contact.AddressInfo" %>
<div>
<asp:Label ID="lbl_line1" AssociatedControlID="txt_line1" runat="server">Line 1:</asp:Label><asp:TextBox ID="txt_line1" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator id="val_line1" runat="server" ErrorMessage="Please include a street address" ControlToValidate="txt_line1" Display="Dynamic">*</asp:RequiredFieldValidator>
</div>
<div>
<asp:Label ID="lbl_line2" AssociatedControlID="txt_line2" runat="server">Line 2:</asp:Label><asp:TextBox ID="txt_line2" runat="server"></asp:TextBox>
</div>
<div>
<asp:Label ID="lbl_zip" AssociatedControlID="txt_zip" runat="server">Zip code:</asp:Label><asp:TextBox ID="txt_zip" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator id="val_zip" runat="server" ErrorMessage="Please include a zip code" ControlToValidate="txt_zip" Display="Dynamic">*</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator id="regVal_zip" ControlToValidate="txt_zip" ErrorMessage="Zip code must be made up of integers in the format xxxxx" ValidationExpression="^\d{5}$" Runat="server" Display="Dynamic">*</asp:RegularExpressionValidator>
</div>
<div>
<asp:Label ID="lbl_city" AssociatedControlID="txt_city" runat="server">City:</asp:Label><asp:TextBox ID="txt_city" runat="server" CssClass="disabled"></asp:TextBox>
</div>
<div>
<asp:Label ID="lbl_state" AssociatedControlID="ddl_state" runat="server">State:</asp:Label><asp:DropDownList ID="ddl_state" runat="server" Enabled="false"></asp:DropDownList>
</div>
<div>
<asp:Label ID="lbl_edit" AssociatedControlID="chk_edit" runat="server">Edit City/State:</asp:Label><asp:CheckBox ID="chk_edit" runat="server" />
</div>
AddressInfo codebehind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MFRI.Common.Contact;
using System.Text;
using System.Globalization;
using System.Threading;
using MFRI.Common;
namespace MFRI.Controls.Contact
{
public partial class AddressInfo : System.Web.UI.UserControl
{
private bool _editable = false;
private bool _allowStateCityEdit = false;
protected bool AllowStateCityEdit{
set { _allowStateCityEdit = value; }
}
protected ClientScriptManager clientScriptManager
{
get { return Page.ClientScript; }
}
protected void Page_Load(object sender, EventArgs e)
{
txt_city.Attributes.Add("readonly", "readonly");
RegisterEditCityStateScript();
if (_editable)
RegisterZipCodeScript();
}
public void InitControl(bool editable, Address address)
{
InitStateDropDown();
if (!_allowStateCityEdit)
{
lbl_edit.Visible = false;
chk_edit.Visible = false;
}
_editable = editable;
if (!_editable)
{
txt_line1.Enabled = false;
val_line1.Enabled = false;
txt_line2.Enabled = false;
txt_city.Enabled = false;
txt_zip.Enabled = false;
val_zip.Enabled = false;
regVal_zip.Enabled = false;
ddl_state.Enabled = false;
chk_edit.Enabled = false;
}
else
{
txt_zip.Attributes.Add("onblur", "GetCityState('" + txt_city.ClientID + "','" + ddl_state.ClientID + "','" + txt_zip.ClientID + "');");
chk_edit.Attributes.Add("onClick", "ToggleCityState('" + txt_city.ClientID + "','" + ddl_state.ClientID + "','" + txt_zip.ClientID + "')");
}
if (address != null)
{
txt_line1.Text = address.Line1;
txt_line2.Text = address.Line2;
txt_city.Text = address.City;
txt_zip.Text = SafeConvert.ToString(address.Zip);
ddl_state.SelectedValue = SafeConvert.ToString((int)address.State);
}
}
private void RegisterZipCodeScript(){
if (!clientScriptManager.IsClientScriptBlockRegistered(this.GetType(), "zipCodeScript"))
{
StringBuilder script = new StringBuilder();
script.Append("function GetCityState(txtCityId,ddlStateId,txtZipId) {\n");
script.Append(" var textZip = document.getElementById(txtZipId);\n");
script.Append(" var zipCode = parseFloat(textZip.value);\n");
script.Append(" if(isNaN(zipCode)){\n");
script.Append(" var txtCity = document.getElementById(txtCityId);\n");
script.Append(" var ddlState = document.getElementById(ddlStateId);\n");
script.Append(" txtCity.value = '';\n");
script.Append(" ddlState.selectedIndex = 0;\n");
script.Append(" }\n");
script.Append(" else{\n");
script.Append(" MFRI.Controls.Contact.ZipCodeService.GetCityState(zipCode, txtCityId, ddlStateId, SucceededCallback);\n");
script.Append(" }\n");
script.Append("}\n");
script.Append("function SucceededCallback(result) {\n");
script.Append(" var txtCity = document.getElementById(result[0]);\n");
script.Append(" txtCity.value = result[2];\n");
script.Append(" var ddlState = document.getElementById(result[1]);\n");
script.Append(" var stateId = result[3];\n");
script.Append(" for(i=0; i<ddlState.options.length; i++){\n");
script.Append(" if(ddlState.options[i].value == stateId){\n");
script.Append(" ddlState.selectedIndex = i;\n");
script.Append(" }\n");
script.Append(" }\n");
script.Append("}\n");
clientScriptManager.RegisterClientScriptBlock(this.GetType(), "zipCodeScript", script.ToString(), true);
}
}
private void RegisterEditCityStateScript()
{
if (!clientScriptManager.IsClientScriptBlockRegistered(this.GetType(), "editCityState"))
{
StringBuilder script = new StringBuilder();
script.Append("function ToggleCityState(txtCityId, ddlStateId, txtZipId) {\n");
script.Append(" var txtCity = document.getElementById(txtCityId);\n");
script.Append(" var ddlState = document.getElementById(ddlStateId);\n");
script.Append(" if(ddlState.disabled == true){\n");
script.Append(" txtCity.removeAttribute('readonly');\n");
script.Append(" ddlState.disabled = false;\n");
script.Append(" }\n");
script.Append(" else{\n");
script.Append(" txtCity.setAttribute('readonly', 'readonly');\n");
script.Append(" ddlState.disabled = true;\n");
script.Append(" GetCityState(txtCityId,ddlStateId,txtZipId); \n");
script.Append(" }\n");
script.Append("}\n");
clientScriptManager.RegisterClientScriptBlock(this.GetType(), "editCityState", script.ToString(), true);
}
}
private void InitStateDropDown(){
CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
TextInfo textInfo = cultureInfo.TextInfo;
ddl_state.Items.Add(new ListItem("Select a state","-1"));
foreach (StateType state in Enum.GetValues(typeof(StateType)))
{
string displayName = state.ToString().ToLower();
displayName = displayName.Replace('_', ' ');
ddl_state.Items.Add(new ListItem(textInfo.ToTitleCase(displayName), state.GetHashCode().ToString()));
}
}
public Address GetAddress()
{
Address address = new Address();
address.Line1 = txt_line1.Text;
address.Line2 = txt_line2.Text;
address.State = (StateType)Enum.ToObject(typeof(StateType), SafeConvert.ToInt(ddl_state.SelectedValue));
address.City = txt_city.Text;
address.Zip = SafeConvert.ToInt(txt_zip.Text);
return address;
}
}
}
I figured it out finally.
Each addressInfo Control is created on the fly by addressInfoGroup. After instantiation, addressInfoGroup calls the 'initControl' method of the newly created addressInfo control. Within that init function I retrieve a few clientID values:
txt_zip.Attributes.Add("onblur", "GetCityState('" + txt_city.ClientID + "','" + ddl_state.ClientID + "','" + txt_zip.ClientID + "');");
chk_edit.Attributes.Add("onClick", "ToggleCityState('" + txt_city.ClientID + "','" + ddl_state.ClientID + "','" + txt_zip.ClientID + "')");
Because of my reference to the clientID's, all of the controls within addressInfo retain the markup Id's. If I comment those lines out, .NET generates the proper Id's. This has something to do with WHEN these lines are called. When I moved the lines into addressInfo's postback, everything worked as expected.
So end result: If a parent control tells a child control to reference a clientID, all of the child controls clientID's seem to malfunction.
Have you thought about using a ListView control to dynamically create and display your Address controls on the fly? You would have one instance of the control hard-coded on the page and then in your ListView's ItemTemplate you would put in your Address control and databind it to the data in your ListView's DataSource property.
Have you tried explicitly setting the ID value of the dynamically added AddressInfo controls? For instance, in the Page_Load of the AddressInfoGroup:
protected void Page_Load(object sender, EventArgs e)
{
if (_controlListToBind != null && _controlListToBind.Count > 0)
{
NumberOfControls = _controlListToBind.Count;
int index = 0;
foreach (Address address in _controlListToBind)
{
AddressInfo addressInfo = (AddressInfo)LoadControl("AddressInfo.ascx");
addressInfo.ID = String.Format("AddressInfo{0}", index++);
addressInfo.InitControl(Editable, address);
plc_infoCtrls.Controls.Add(addressInfo);
}
}
else
{
if (NumberOfControls <= 0)
NumberOfControls = 1;
for (int i = 0; i < NumberOfControls; i++)
{
AddressInfo addressInfo = (AddressInfo)LoadControl("AddressInfo.ascx");
addressInfo.ID = String.Format("AddressInfo{0}", i);
addressInfo.InitControl(Editable, null);
plc_infoCtrls.Controls.Add(addressInfo);
}
}
RefreshButtons();
}

Categories

Resources