How to use a web user control in code only (no rendering)? - c#

I have a user control which has panels and other gui controls. It's used like any user control in rendering a web page. However I have a need to use a new instance of it and use it in code only without rendering it as it has business logic which I want to use. However it gets object null reference errors during run whenever a gui control is referenced in code, for example: pnlSomePanel.Visible = true;
How do I use a user control in code only (without it being rendered)? Using .NET 4.0.

Technically, you should just be able to create a new instance of the code-behind class (assuming an asp.net web application and not a web site).
However, if there is business logic embedded in that user control, I would suggest moving it into a separate class or exposing the business logic as a static method with an appropriate set of parameters.

How about this...
Add a reference to your module on the page.
<%# Reference Control="~/modules/MyModule.ascx" %>
Then, you can create an instance of that module in your code behind using the class name of the module.
modules_MyModule ctrl = LoadControl("~/modules/MyModule.ascx") as modules_MyModule;
ctrl.SomeMethod();
The next step would be to add it to a parent container, but if you skip that step, you should still have a functional object in the code behind. Not totally sure if it will work, but in theory it should.

Related

User-control based program

I am trying to create a new Windows Store-app, but before creating too many user-controls, I will like to know something that I have no luck googling
If my program only have one page, and the code thereby is based by user-controls, could it then be possible to use GoBack, or should I implement my own way to do that?
And if I need my own way to override GoBack, can I then override GoBack in the Page, or should I override it in general for the whole app?
If you're going to keep the same instance of your page and just switch the user control that is displayed then you'll need to reimplement the existing navigation framework. For it to work you need to be calling Frame.Navigate() to switch between different page instances.
To do that in your case you could still only have a single page class but instead of just replacing the user control inside the same instance you could call Frame.Navigate() with the same page class and then inside it display the correct user control based on the parameter that you pass in. In this case you can use the existing navigation framework to navigate between the page instances.

Can I use parent(web page) property in web user control?

How can I use parent(web page) property in web user control?
One more question:- How can I access the shared class(i.e. class in App_Code folder) property in web user control.
Thanks
You can use this.Page in asp.net user control to refer to page and it will always give you page in which that control is added.
You can access any public class declared in App_code folder directly in any user control without problem. Be careful of namespace and make sure to compile your project if you are having issues to access the class.
You could but I am not sure it would be a clean / full OOP approach, how about setting a public property or calling a public method of your user control from the page passing to it the value you need to use in the control?
this because the page hosting the control should be generic and is the page which contains the control not the other way round.
If this does not fit you, then you can take the control's Page property and cast it to the class of your page then you will be able to access its property but this will make your control specific instead of generic and it will only work when the control is hosted in pages of that exact type/class.
You have to mark the property as Public.
var myVar = ((ParentPageClass)this.Page).YourProperty;
To access the shared class you have to specify the namespace of that class:
YourProject.SomeNamespace.YourClass
or to include the namespace in your .ascx.cs file
using YourProject.SomeNamespace;
It's a cleaner aproach to pass the parameter to the user control from the parent page.

Re-using another page section

I have created a web page that I use as a small dashboard to hold issue or no issue. It works great. The page uses an .aspx and .aspx.cs. I would like to be able to reuse the information on this page on other pages. My site already uses master pages and I have not been able to find an easy way to include this information.
How can I use an include from a page that has coding in the code behind easily?
Typically you use Web User Controls for this.
Web User Controls allow you to package up other controls into one that you can drop onto multiple pages. They are great for common UI items such as address entries, dashboards, etc. Basically anything that needs to be the same across multiple pages.
At the risk of seeming very obvious - do you mean usercontrols. These will allow you to reuse chunks of functionality across your site.
I guess this question falls into two categories: User Controls, and Code Reuse. Not sure which one you are after.
User Controls
If you are talking about the controls on your page you will want to create a common user control.
Code Reuse
You need to create a common class (whether it is static or not depends on how you intend to use it) and define functions within that class.
For instance, lets say you have a page that you want to print "Hello World!" on any aspx/.cs page.
You could do this
public static class MyClass
{
public string PrintHelloWorld()
{
return "Hello World!";
}
}
Then you call it from any of your pages like so:
MyClass.PrintHelloWorld();
Right click on the project > Add New Item...
Select User Control (.ascx)
Put your markup & code behind there.
Then you add that control in any other page (includding other controls [although I wouldn't recommend that])
It sounds like you may want to create an ascx User Control.
http://msdn.microsoft.com/en-us/library/ie/2x6sx01c.aspx

ASP: Extend control (ASCX) and access base markup file from subclass code

I'm building form validation controls for our C# ASP application. The bulk of the work is handled by a BaseValidator control (subclassing System.Web.UI.UserControl), which also has the markup for the validation output. This is then extended by subcontrols like PasswordValidator, that provides the Validate method and any extra fields needed by that validator control.
(The end goal is to have controls like <uc1:PasswordValidator ControlId="txtPassword" /> which we can plop into any form with minimum duplication.)
However, PasswordValidator.ascx.cs cannot access the form elements defined in BaseValidator.ascx; the only way I've found to do so is to duplicate the markup in each subcontrol's *.ascx file. How can I extend BaseValidator.ascx.cs and access BaseValidator.ascx's markup in the subclass?
I'm pretty sure you'll have to create Server Controls to accomplish this. Meaning, you'll need to generate the outputted Markup from code in the control rather than in the .ascx file.
If you have a true baseclass for your BaseValidator control which your PasswordValidator extends, then any markup/controls in the baseclass should be available through protected properties. I would even go so far as to argue that a true base should not have an ascx portion. The base class should provide methods and properties that expose controls to built on the fly (probably during Page_Init to maintain viewstate).
If you have 2 separate controls on the same page, your parent page can be modified to provide brokerage methods to allow such communication.
If you have the PasswordValidator and you just need the controls/markup, you can use the LoadControl method to create an instance of the BaseControl in memory, access its controls/markup programmatically and either add it or destroy it depending on what you want to do with it.
Barring any of that, it would be just as #Shawn said. Server controls.
Thanks for the suggestions.
I solved this using a service and the strategy pattern. There is a central FieldValidator class which provides validation for any user interface. For the web interface, these methods are exposed through a WebService and (through the WebService) a UserControl. There are no issues with accessing the page elements, because there is now only one UserControl class that stands between the form and the WebService.
For example, <uc1:FieldValidator ControlType="Password" ControlToValidate="txtPassword" runat="server" > will plop down fully-functional clientside and serverside validation, with no need for code behind. Great! :)
(I mentioned resolution a while back in a reply to my question, but I can't mark that as answered.)

Failing to add controls to a page dynamically

I'm adding a User Control for each record pulled up in a data reader, here's the basic loop:
while (dr.Read())
{
ImageSelect imgSel = new ImageSelect(dr["Name"].ToString());
myPanel.Controls.Add(imgSel);
}
The problem is that there are no controls added to the page, I check the html output and there is my panel, with nothing in it.
I even stepped through the code in the debugger, and verified that myPanel.Controls gets a control added on each loop, with the count being 6, no errors, but then they dont show up on the page.
I've run the above code in the Page_Init and Page_Load events, both with the same result.
EDIT:
Ok so I've switched to using LoadControl("....ascx") to get my control instance, which is now working. But originally I was also passing in data via the controls constructor.. Is this still possible or do I just need to set them via get/sets?
EDIT 2:
Thanks to Freddy for pointing out that the LoadControl has an overload where you CAN pass in constructor params, see accepted answer.
EDIT 3:
After trying this method both with and without the constructor. I have found its better to just use setters for any properties I want the control to have versus trying to use the passed in object array for my constructor.
Update: As Steve pointed out, the overload of LoadControl that uses the type won't take into account the controls in the ascx. This is also mentioned in this answer: Dynamically Loading a UserControl with LoadControl Method (Type, object[]).
As I mentioned before, the get/set are more in line with the asp.net model, so I recommend using that with the LoadControl variation that receives the user control path. That said, the Steve's version is an interesting alternative: http://www.grumpydev.com/2009/01/05/passing-parameters-using-loadcontrol/.
My take is the LoadControl with type is meant to be used with web custom controls instead.
If it is an user control you should use LoadControl(usercontrolpath) to get the instance of the user control.
You can use a constructor by doing:
var name = dr["Name"].ToString();
var imgSel = LoadControl(typeof(ImageSelect), new object[]{ name });
myPanel.Controls.Add(imgSel);
Notice that depending on the project model you are using, you need to add a Reference to the aspx to use it with the typeof variation:
<%# Reference Control="~/somepath/myusercontrol.ascx" %>
Ps. I usually use the set/get for controls as I find them more in line with the asp.net model
To add UserControls you must call the LoadControl method passing in the path to the .ascx file. You can not create them by just instantiating the object the .ascx file inherits from.
A UserControl consists of both the markup and the class in the code behind. The markup contains a link to the class behind, but the class behind does not know where the markup lives and therefore can not be created on it's own.

Categories