I am using BuildManager Class to Load a dynamically generated ASPX File, please note that it does not have a corresponding .cs file.
Using Following code I am able to load the aspx file, I am even able to loop through the control collection of the dynamically created aspx file, but when I am assigning values to controls they are not showing it up. for example if I am binding the value "Dummy" to TextBox control of the aspx page, the textbox remains empty.
Here's the code that I am using
protected void Page_Load(object sender, EventArgs e)
{
LoadPage("~/Demo.aspx");
}
public static void LoadPage(string pagePath)
{
// get the compiled type of referenced path
Type type = BuildManager.GetCompiledType(pagePath);
// if type is null, could not determine page type
if (type == null)
throw new ApplicationException("Page " + pagePath + " not found");
// cast page object (could also cast an interface instance as well)
// in this example, ASP220Page is a custom base page
System.Web.UI.Page pageView = (System.Web.UI.Page)Activator.CreateInstance(type);
// call page title
pageView.Title = "Dynamically loaded page...";
// call custom property of ASP220Page
//pageView.InternalControls.Add(
// new LiteralControl("Served dynamically..."));
// process the request with updated object
((IHttpHandler)pageView).ProcessRequest(HttpContext.Current);
LoadDataInDynamicPage(pageView);
}
private static void LoadDataInDynamicPage(Page prvPage)
{
foreach (Control ctrl in prvPage.Controls)
{
//Find Form Control
if (ctrl.ID != null)
{
if (ctrl.ID.Equals("form1"))
{
AllFormsClass cls = new AllFormsClass();
DataSet ds = cls.GetConditionalData("1");
foreach (Control ctr in ctrl.Controls)
{
if (ctr is TextBox)
{
if (ctr.ID.Contains("_M"))
{
TextBox drpControl = (TextBox)ctr;
drpControl.Text = ds.Tables[0].Rows[0][ctr.ID].ToString();
}
else if (ctr.ID.Contains("_O"))
{
TextBox drpControl = (TextBox)ctr;
drpControl.Text = ds.Tables[1].Rows[0][ctr.ID].ToString();
}
}
}
}
}
}
}
I saw that you got part of your code from How To Dynamically Load A Page For Processing. Read the comments too as this one by Mike.
Invert this:
((IHttpHandler)pageView).ProcessRequest(HttpContext.Current);
LoadDataInDynamicPage(pageView);
To this:
LoadDataInDynamicPage(pageView);
((IHttpHandler)pageView).ProcessRequest(HttpContext.Current);
In this case changing the order of the calls does change the end result I think. The inverse of Commutativity property. :)
Related
I have a lot of control values in my C# app. I'm wondering if there is a possibility to store and read the entire available control values at once, instead of the code below.
Please note, the code below is only for 1 groupBox. I've 8 of them, thus this will generate a lot of code to implement it (8 times the code below).
groupBox are copies of each other
the code below works
I store the data using serializing the configData class (works).
private void uiStateWriteToData()
{
configData.datSensor4mA1 = (int)uiSensor4mA1.Value;
configData.datSensor20mA1 = (int)uiSensor20mA1.Value;
configData.datSensorPidP1 = (int)uiSensorPidP1.Value;
configData.datSensorPidI1 = (int)uiSensorPidI1.Value;
configData.datSensorPidD1 = (int)uiSensorPidD1.Value;
configData.datSensorPidS1 = (int)uiSensorPidS1.Value;
configData.datSensor1InToOutput1 = uiSensor1Out1.Enabled;
configData.datSensor1InToOutput2 = uiSensor1Out2.Enabled;
configData.datSensor1InToOutput3 = uiSensor1Out3.Enabled;
}
private void uiStateUpdateFromData()
{
uiSensor4mA1.Value = configData.datSensor4mA1;
uiSensor20mA1.Value = configData.datSensor20mA1;
uiSensorPidP1.Value = configData.datSensorPidP1;
uiSensorPidI1.Value = configData.datSensorPidI1;
uiSensorPidD1.Value = configData.datSensorPidD1;
uiSensorPidS1.Value = configData.datSensorPidS1;
uiSensor1Out1.Enabled = configData.datSensor1InToOutput1;
uiSensor1Out2.Enabled = configData.datSensor1InToOutput2;
uiSensor1Out3.Enabled = configData.datSensor1InToOutput3;
}
I don't know if there are any frameworks that can do that, but maybe you could come up with your own utility that writes control values into xml file based on the control hierarchy, types and names.
Here is how it may look (rather in pseudo-code):
private static void WriteControlValuesToXml(XmlDocument document, XmlNode parentNode, Control currentControl)
{
// if current control is container, writing its children values
if (currentControl.Controls.Count > 0)
{
var addedNode = AddNode(parentNode, currentControl.Name);
foreach (Control childControl in currentControl.Controls)
WriteControlValuesToXml(document, addedNode, childControl);
}
else
{
// if current control is not container, writing control values
if (currentControl is CheckBox)
{
var checkBox = (CheckBox)control;
AddNode(parentNode, currentControl.Name, "CheckBox", checkBox.Checked);
}
if (currentControl is TextBox)
{
var textBox = (TextBox)control;
AddNode(parentNode, currentControl.Name, "TextBox", textBox.Text);
}
// ... other known controls
}
}
And following the same logic, you can implement reading the same control values from file.
I have a UserControl which I am loading into a div which is inside an UpdatePanel. Here is my code for loading it:
controls.IDLControl IdlControl = LoadControl(#"~/controls/IDLControl.ascx") as controls.IDLControl;
IdlControl.ClientIDMode = ClientIDMode.Static;
IdlControl.ID = "IDLControl";
spGroup.Controls.Clear();
spGroup.Controls.Add(IdlControl);
And here is my code for trying to retrieve an instance of it:
controls.IDLControl IdlControl = RecursiveFindControl(this, "IDLControl") as controls.IDLControl;
private Control RecursiveFindControl(Control targetControl, string findControlId) {
if (targetControl.HasControls()) {
foreach (Control childControl in targetControl.Controls) {
if (childControl.ID == findControlId) {
return childControl;
}
RecursiveFindControl(childControl, findControlId);
}
}
return null;
}
But, all I get is null. I need help on figuring this out.
AFAIK, I need to re-add the control to the page on pre-init but it is one of the controls that can be added depending on which option is selected from a drop down list (which also is filled dynamically). I am stuck trying to figure out how to make this work.
You can try something like this to add your control back in the Page_Init based on the option selected in your DropDownList.
protected void Page_Init(Object sender, EventArgs e)
{
if (IsPostBack)
{
if (drpYourDropDown.Items.Count > 0 && drpYourDropDown.SelectedItem.Text == "yourOption")
{
AddIDLControl();
}
}
}
private void AddIDLControl()
{
controls.IDLControl IdlControl = LoadControl(#"~/controls/IDLControl.ascx") as controls.IDLControl;
IdlControl.ClientIDMode = ClientIDMode.Static;
IdlControl.ID = "IDLControl";
spGroup.Controls.Clear();
spGroup.Controls.Add(IdlControl);
}
I have a class that is a list of class objects.
[Serializable]
public class UserRequestOrders
{
private List<RTORequestOrder> m_thisUsersOrders = new List<RTORequestOrder>();
public List<RTORequestOrder> RequestOrders
{
get { return m_thisUsersOrders; }
set { m_thisUsersOrders = value; }
}
}
When I create an instance of this object I need to populate the list variable When m_thisUsersOrders with an existing list of requests (from a viewstate).
MyOrders.RequestOrders = (List<RTODataEntryObjects.RTORequestOrder>)ViewState["vsMyOrders"];
When the page posts back, I cast the viewstate into a list of RTORequestOrder objects, and try to set the RequestOrders property, I get the message that the property or indexer cannot be assigned to. I have a "SET" accessor for the property.
All posts that I have read on this topic state that I need to modify scope in the application settings, but I am not sure how that applies here. I don't have any application settings set.
I am hoping someone can help me understand how I can populate the list from an existing list.
EDIT: Nico, Thanks for your response! Below is the full code from the code behind page. "MyOrders" and "lst" are essentially the same thing. When I am working with "lst" everything works the way that I want it to. The reason that I want to use the "MyOrders" object instead is because I have a method that returns the list as a datatable with only the fields I need to display. (I didnt' show that code because the issue appears to be with the "SET" accessor.) "lst" has the same signiture as the "MyOrders.RequestOrders". Why can I cast the the viewstate into the lst object, but not the MyOrders object?
EDIT: Grant, thanks for your response as well. I don't know how to set breakpoints for ASP pages... :(
public partial class Default3 : System.Web.UI.Page
{
RTODataEntryObjects.UserRequestOrders MyOrders = new RTODataEntryObjects.UserRequestOrders();
List<RTODataEntryObjects.RTORequestOrder> lst = new List<RTODataEntryObjects.RTORequestOrder>();
void Page_PreRender(object sender, EventArgs e)
{
if (ViewState["vsMyOrders"] == null)
{
NewDataGrid.DataSource = (RTODataEntryObjects.UserRequestOrders)ViewState["vsMyOrders"]; // code to show the data in the grid when page loading
}
}
protected void Page_Load(object sender, EventArgs e)
{
NewDataGrid.EnableViewState = true;
NewDataGrid.DataSource = (RTODataEntryObjects.UserRequestOrders)ViewState["vsMyOrders"];
NewDataGrid.DataBind();
}
public void btnSubmit(object sender, EventArgs e)
{
int id = Int32.Parse(TextBox1.Text); // dynamically getting the data from the frontend.
string name = TextBox2.Text; // dynamically getting the data from the frontend.
if (ViewState["vsMyOrders"] != null) // if the view state is already having data then can update the list and assign again to the viewstate later.
{
lst = (List<RTODataEntryObjects.RTORequestOrder>)ViewState["vsMyOrders"];
MyOrders.RequestOrders = (List<RTODataEntryObjects.RTORequestOrder>)ViewState["vsMyOrders"];
}
RTODataEntryObjects.RTORequestOrder thisOrder = new RTODataEntryObjects.RTORequestOrder(id, name, User.Identity.Name, System.Environment.MachineName);
lst.Add(thisOrder); //
MyOrders.AddNew(thisOrder);
ViewState["vsMyOrders"] = MyOrders;
NewDataGrid.DataSource = (IList<RTODataEntryObjects.RTORequestOrder>)ViewState["vsMyOrders"];
NewDataGrid.DataBind();
}
}
I have a page which initially inherited from MastePage.master . And I want to use the same page but with different masterpage(MasterPage2.master) at some other place in my project. For that I am using the following code.
private void Page_PreInit(object sender, EventArgs e)
{
if (Request.QueryString["Update"].ToString() == "New")
{
this.MasterPageFile = "MasterPage2.master";
Content con = new Content();
con = (Content)this.FindControl("Content1");
this.Content1.ContentPlaceHolderID = "ContentPlaceHolder2";
}
}
I am also trying to set the asp content tag's ContentPlaceHolderID to ContentPlaceHolder2 which is from MasterPage2.master. Initially it was ContentPlaceHolder1.
But I am getting null value at con = (Content)this.FindControl("Content1");
Thanks
Page internally stores in private '_contentTemplateCollection' hashtable. it uses ContentPlaceHolderID property as key and stores special class (that will be used to build/initialize Content tag) as a value
- so to change ContentPlaceHolderID value (defined within markup) you need to modify this hashtable, remove old entry linked with old Id and add other entry with new Id
- you need to change ContentPlaceHolderId before creating master page otherwise an exception will be thrown in runtime
- best place to change Ids is Page 'preinit' event and if it is better to change Ids before change master page (if you will change master page at runtime)
To change ContentPlaceHolderID of Content tag, you can use following function in Page PreInit event
public static void AssignContentToNewPlaceHoldersWithinPage(Page pPage, string pOldId, string pNewId)
{
if (pPage == null || string.IsNullOrEmpty(pOldId) || string.IsNullOrEmpty(pNewId))
{
return;
}
// Try to get a reference to private hashtable using fasterflect free reflection library in codeplex (http://fasterflect.codeplex.com/)
// you can replace following line with standard reflection APIs
var lTmpObj = pPage.TryGetFieldValue("_contentTemplateCollection");
if (lTmpObj != null && lTmpObj is Hashtable)
{
var _contentTemplateCollection = lTmpObj as Hashtable;
if (_contentTemplateCollection.ContainsKey(pOldId) && !_contentTemplateCollection.ContainsKey(pNewId))
{
var lTemplate = _contentTemplateCollection[pOldId];
_contentTemplateCollection.Add(pNewId, lTemplate);
_contentTemplateCollection.Remove(pOldId);
}
}
}
function parameter are
pPage is reference to page instance contains content tag
pOldId is ContentPlaceHolderId property value in markup - the Id you want to change
pNewId is the new Id you want to use
I hope that my answer will be useful and I am sorry if my English language is not good
You can dynamically change the Master Page at runtime, but you need to use the same ContentPlaceHolder IDs. That way, your pages will work with either Master Page without adding extra code to change the IDs at runtime.
private void Page_PreInit(object sender, EventArgs e)
{
if (Request.QueryString["Update"].ToString() == "New")
{
this.MasterPageFile = "MasterPage2.master";
}
}
You can even test that your page will work with either Master Page in the Visual Studio design/markup view by changing the MasterPageFile in the <% Page %> directive in the .aspx markup.
The Master Page can be changed by overriding OnPreInit.
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
MasterPageFile = "~/MasterPages/MyOther.Master";
}
But for the ContentPlaceHolders I would suggest to create new ContentPlaceHolders with the same name in both of your MasterPages.
I built custom ASP.NET control and it's working fine when I add it manually (drag and drop) or by code to controls in markup.
The custom control, MsgBox, had resources like JavaScript, CSS and images embedded in and the problem appeared when I tried to Render the control in class to return its HTML code, the Page instance is null and the "GetWebResourceUrl" needs it:
Page.ClientScript.GetWebResourceUrl(.....)
is there any way to get the resourceurl ? Here is my render code:
protected override void RenderContents(HtmlTextWriter writer)
{
using (PlaceHolder plh = new PlaceHolder())
{
if (Page != null)
{
if (DesignMode || Page.Header == null)
RegisterCSSInclude(plh);
}
HtmlGenericControl container = new HtmlGenericControl("div");
container.EnableViewState = false;
container.InnerHtml = "Control html code";
plh.Controls.Add(container);
plh.RenderControl(writer);
}
}
RegisterCSSInclude is method to register my css files:
private void RegisterCSSInclude(Control target)
{
// CSS
bool linkIncluded = false;
foreach (Control c in target.Controls)
{
if (c.ID == "MsgBxStyle")
{
linkIncluded = true;
}
}
if (!linkIncluded)
{
HtmlGenericControl globalCsslink = new HtmlGenericControl("link");
globalCsslink.ID = "MsgBxGStyle";
globalCsslink.Attributes.Add("href", Page.ClientScript.GetWebResourceUrl(typeof(MessageBoxCtrl), "MessageBox.MsgBxStyles.WeDevMsgBox.css"));
globalCsslink.Attributes.Add("type", "text/css");
globalCsslink.Attributes.Add("rel", "stylesheet");
globalCsslink.EnableViewState = false;
target.Controls.Add(globalCsslink);
HtmlGenericControl csslink = new HtmlGenericControl("link");
csslink.ID = "MsgBxStyle";
csslink.Attributes.Add("href", Page.ClientScript.GetWebResourceUrl(typeof(MessageBoxCtrl), "MessageBox.MsgBxStyles." + Style.ToString().ToLower() + ".css"));
csslink.Attributes.Add("type", "text/css");
csslink.Attributes.Add("rel", "stylesheet");
csslink.EnableViewState = false;
target.Controls.Add(csslink);
}
}
Update:
PS: I'm tring to use control in generic handler (ashx) where I call ShowMsgBox method which is a method in a class and not in a page or user control.
ShowMsgBox method should create an instance of MsgBox control and render it then return the html code to ashx class :
var htmlCode = MyClass.ShowMsgBox("myMsg");
context.Response.write(htmlCode);
I built a custom ASP.NET control ...
I'm tring to use control in generic handler (ashx) ... not in a page or user control.
A Page is a handler. You want to use a convenience provided by the Page class, but you don't want to inherit from Page. The niceties of Page, such as ClientScript, expect a Page from which to get various information.
You can provide a dummy Page object to your control by setting the Page property of your custom Control:
this.Page = new Page();
...then you will need to set various properties (assuming they are public) which are expected by ClientScriptManager.GetWebResourceUrl():
this.Page.Foo = "bar";
then you can call:
this.Page.ClientScript.GetWebResourceUrl(...);
If this is the specific class that inherits from WebControl page shouldn't be null. If its another class that you are rendering as part of a hierarchy you can add a parameter of type Page and pass the reference of the current page to it.