Which method does Page class invoke to instantiate its controls? I want to override it so as to be able to instantiate only certain controls.
there is a nice explanation here: ASP.NET Page Life Cycle Overview
an article like this is a must read if you do ASP.NET web form development.
just that you have some background before just palying around with Page_Load and Page_Init without a clue, in the article there is a table with the list of all events in the right order and full explanation for each of them.
if you open reflector it has a function called :
loadControlRecursivly ( or something like that) - thats where he laods it.
here it is :
internal virtual void LoadRecursive()
{
if (this._controlState < ControlState.Loaded)
{
if (this._adapter != null)
{
this._adapter.OnLoad(EventArgs.Empty);
}
else
{
this.OnLoad(EventArgs.Empty);
}
}
if ((this._occasionalFields != null) && (this._occasionalFields.Controls != null))
{
string errorMsg = this._occasionalFields.Controls.SetCollectionReadOnly("Parent_collections_readonly");
int count = this._occasionalFields.Controls.Count;
for (int i = 0; i < count; i++)
{
this._occasionalFields.Controls[i].LoadRecursive();
}
this._occasionalFields.Controls.SetCollectionReadOnly(errorMsg);
}
if (this._controlState < ControlState.Loaded)
{
this._controlState = ControlState.Loaded;
}
}
If your controls are not dynamically instantiated then you can't in the normal page lifecycle.
Related
In the ascx.cs file I'm dynamically generating buttons. In .aspx file I add the control to the form. The control itself renders well, but when the buttons are clicked I get this error
An error has occurred because a control with id 'ctl03' could not be
located or a different control is assigned to the same ID after
postback.
DestopControl.ascx.cs
public partial class DesktopControl : PlaceHolder
{
public void Build()
{
for (int i = 0; i < 10; i++)
{
Button button = new Button()
{
Width = 50,
Height = 50,
ID = string.Format("button{0}", i),
Text = i.ToString()
};
button.Click+=new EventHandler(button_Click);
}
}
}
Default.aspx.cs
DesktopControl desktop = new DesktopControl();
desktop.Build();
MainContent.Controls.Add(desktop);
After reading the comments (little hard to read the code-part of the comments) it appears that yes, you are generating your controls inside an if(!isPostBack){}; well, looks like it's in the else part of that if statement.
You have to generate your controls every time the page posts back, as the page_load gets fired before your button click. So once the controls have been re-created the code will continue on to your button click handler, where the controls should be available to handle.
Essentially, take ReloadUI(Session["ui"]); OUT of the if(!isPostBack){}else{} statement. Put it after your if statement.
Like this:
if (!isPostBack){
// my first load code
}else{
// my postback code
}
// load all my dynamic controls here
ReloadUI(Session["ui"]);
Found a solution:
Every time there is a new UI I call this ClearScreen() which does the trick.
The error on 'ctl03' was a menu control which was generating it's own ID and somehow wasn't available on postback. I assigned an ID to it. But I guess all the issue went away with this ClearScreen() method.
private void ClearScreen()
{
try
{
List<Control> controls = new List<Control>();
foreach (Control control in MainContent.Controls)
{
controls.Add(control);
}
for (int i = 0; i < controls.Count; i++)
{
if (!(controls[i].GetType() == typeof(LiteralControl) || controls[i].GetType() == typeof(ScriptManager)))
{
MainContent.Controls.Remove(controls[i]);
}
}
}
catch (Exception ex)
{
}
}
In asp.net Web application, i write code for datalist paging like this :
PagDat = new PagedDataSource();
PagDat.AllowPaging = true;
PagDat.PageSize = 10;
PagDat.CurrentPageIndex = **currentpage**;
PagDat.DataSource = ds.Tables[0].DefaultView;
dtlstMagazine.DataSource = PagDat;
dtlstMagazine.DataBind();
In this "currentpage" is a integer varaible which i declared as a static. I think it could be conflict when more user access this page am i right?
Yes your are right.
You should Save your PageDataSouce page index in State Management
object. using static variable is not a good approach in web
application for such page level operations.
Create CurrentPage property:
public int CurrentPage
{
get
{
// look for current page in ViewState
object o = this.ViewState["_CurrentPage"];
if (o == null)
return 0; // default page index of 0
else
return (int) o;
}
set
{
this.ViewState["_CurrentPage"] = value;
}
}
Check following link for more information:
Adding Paging Support to the Repeater or DataList with the PagedDataSource Class
I have an ASP.net web page that is heavily used. The problem is that the ViewState is becoming huge! The page has an ASP.net GridView with paging and sorting. However, the size of the ViewState seems totally out of proportion with what's on the page.
I would like to know how to browse the contents of the ViewState in the Visual Studio 2010 debugger so that I can know what data is being saved in the ViewState.
I'm not sure if it will suit your needs, but you can check out this tool:
http://www.pluralsight-training.net/community/media/p/51688.aspx
And here's helper class you check out which dumps the contents of the ViewState to a log file. Obviously, you can modify it as needed.
// Written by Greg Reddick. http://www.xoc.net
public static void SeeViewState(string strViewState, string strFilename)
{
if (strViewState != null)
{
Debug.Listeners.Clear();
System.IO.File.Delete(strFilename);
Debug.Listeners.Add(new TextWriterTraceListener(strFilename));
string strViewStateDecoded = (new System.Text.UTF8Encoding()).GetString(Convert.FromBase64String(strViewState));
string[] astrDecoded = strViewStateDecoded.Replace("<", "<\n").Replace(">", "\n>").Replace(";", ";\n").Split('\n');
Debug.IndentSize = 4;
foreach (string str in astrDecoded)
{
if (str.Length > 0)
{
if (str.EndsWith("\\<"))
{
Debug.Write(str);
}
else if (str.EndsWith("\\"))
{
Debug.Write(str);
}
else if (str.EndsWith("<"))
{
Debug.WriteLine(str);
Debug.Indent();
}
else if (str.StartsWith(">;") || str.StartsWith(">"))
{
Debug.Unindent();
Debug.WriteLine(str);
}
else if (str.EndsWith("\\;"))
{
Debug.Write(str);
}
else
{
Debug.WriteLine(str);
}
}
}
Debug.Close();
Debug.Listeners.Clear();
//Get into the debugger after executing this line to see how .NET looks at
//the ViewState info. Compare it to the text file produced above.
Triplet trp = (Triplet) ((new LosFormatter()).Deserialize(strViewState));
}
}
And you can call it like this:
DebugViewState.SeeViewState(Request.Form("__VIEWSTATE"), "c:\temp\viewstate.txt")
See this link for more details:
http://www.xoc.net/works/tips/viewstate.asp
I have a control declared with PartialCaching attribute, like this:
[PartialCaching(60 * 60 * 12)]
public class MyControl : Control {
// control contents ...
}
but I create it in code, using new keyword. The problem is that if the control is in cache I must not create the control again the next time, but I need to add the control to the page hierarchy, otherwise nothing is going to be rendered. What I need in pseudo-code is something like this:
if (myControlIsCached) {
var ctl = ???; // something that represents the cached control
// e.g. could be: new LiteralControl( myControlCachedData )
this.Controls.Add( ctl );
}
else {
var ctl = new MyControl();
// setup control ...
this.Controls.Add( ctl );
}
What is the correct way of doing it?
Thanks people.
I believe you are looking to do something like this:
Control possiblyCachedControl = LoadControl("path to control");
MyControlType control = null;
if (possiblyCachedControl is MyControlType)
{
//control wasn't cached
control = possiblyCachedControl as MyControlType;
}
else if (possiblyCachedControl is PartialCachingControl && ((PartialCachingControl)possiblyCachedControl).CachedControl != null)
{
//control was cached
control = (MyControlType)((PartialCachingControl)possiblyCachedControl).CachedControl;
}
if (control != null)
{
//use the control
}
What I am trying to do is accessing Page Controls at Page_Load, and make a database query, and make controls visible or not visible.
Here is the Code:
foreach (Control thiscontrol in ContentPlaceHolderBody.Controls) {
try {
if (thiscontrol.ID.Contains("TextBox") || thiscontrol.ID.Contains("Label")) {
string dummy = thiscontrol.ID;
bool IsValid = db.Roles.Any(a => a.controlName == dummy);
if (IsValid == false)
thiscontrol.Visible = false;
}
else if (thiscontrol.ID.Contains("UpdatePanel")) {
foreach (Control UPcontrols in ((UpdatePanel)thiscontrol).ContentTemplateContainer.Controls) {
if (UPcontrols.ID.Contains("TextBox") || UPcontrols.ID.Contains("DropDownList")) {
bool UPIsValid = db.Roles.Any(a => a.controlName == UPcontrols.ID);
if (UPIsValid == false)
UPcontrols.Visible = false;
}
}
}
}
catch { }
}
My Problem is with the UPcontrols! It should retrieve the controls within the UpdatePanel, but the thing is it doesn't do its job, except in the debug mode!
When I add a breakpoint, everything is OK, but when I run the web application, it doesn't find any components within the UpdatePanel...
Try this one:
ControlCollection cbb = updatepanel1.Controls;
ControlCollection cb = cbb[0].Controls;
initialize_Controls(cb);
public void initialize_Controls(ControlCollection objcontrls)
{
foreach (Control tb in objcontrls) {
if (tb is TextBox)
((TextBox)tb).Text = "";
if (tb is Panel) {
ControlCollection cbcll = tb.Controls;
foreach (Control tbb in cbcll) {
if (tbb is TextBox)
((TextBox)tbb).Text = "";
}
}
}
}
First find controls from updatepanel i.e ContentTemplate, then find controls from contentTemplate which contain all controls in it.
This seems like a very bizarre design. That is, using control IDs for such purposes is rather unusual.
Nevertheless, you need a recursive method here to do a deep walk of every control on the page. Your method will not work if the UpdatePanel is contained within another control.
Have a check on this article
http://www.codeproject.com/Articles/24178/The-magical-effects-of-the-UpdatePanel-control-in