i have 1 aspx page and 1 user control. I want to access hidden field of aspx page in the code behind of user control page.
Please help me on this.
Use Page.FindControl
var hiddenField = this.Page.FindControl("hiddenField") as HiddenField;
Here's one way to do it:
Expose the hidden field control as a public property of the containing page.
In the user control, cast Page to the specific type of the containing page.
Access the property.
I don't really like this approach as it tightly couples the user control with the containing page type, but this seems to happen frequently in web forms.
Example
public class MyPage : Page
{
public HtmlInputHidden MyHiddenField
{
get{ return this.hdnField1; }
}
}
public class MyUserControl : UserControl
{
protected override OnLoad( EventArgs e )
{
MyPage p = (MyPage)Page;
HtmlInputHidden h = p.MyHiddenField;
}
}
Example 2 - Parent Initializes Child
This example is cleaner in that the child is agnostic of its parent. However, it requires the parent to initialize the child at the right time (which can be tricky with the web form page lifecycle) and requires that the parent have knowledge of the inner workings of the child.
public class MyPage : Page
{
protected override OnLoad( EventArgs e )
{
this.MyUserControl.Initialize( this.MyHiddenField );
}
}
public class MyUserControl : UserControl
{
public void Initialize( HtmlInputHidden input )
{
// now child user control has access to the data without needing to know
// about its parent
}
}
Related
This question already has answers here:
Is there a way to reach a `protected` member of another object from a derived type?
(7 answers)
Closed 9 years ago.
I'm coding a WP7 GUI and have designed a Control class, and a ParentControl class that derives from Control and has a list of child controls. However, when adding a child to a ParentControl instance, I'm unable to access the child's parent reference because I set it to be 'protected' from users of the controls.
The exact error is
"Cannot access protected member 'Control.Parent' via a qualifier of type 'Control';
the qualifier must be of type 'ParentControl' (or derived from it)"
public abstract class Control //such as a button or radio button
{
public ParentControl Parent { get; protected set; }
}
public abstract class ParentControl : Control //such as a panel or menu
{
protected List<Control> children = new List<Control>();;
public void AddChild(Control child, int index)
{
NeedSizeUpdate = true;
if (child.Parent != null)
child.Parent.RemoveChild(child);
child.Parent = this; //How do I access the parent?
children.Insert(index, child);
OnChildAdded(index, child);
}
}
How might I fix this?
Yes, this is because other things may derive from Control, and ParentControl can only access base members of controls it derives from. For instance, if Control2 derived from Control, then ParentControl would not derive from Control2 and so could not access it's base members.
So, you either make Parent a public property, or if you want to keep it hidden away from general users of the control, you could make access via an interface, and implement it explicitly:
interface IChildControl
{
ParentControl Parent { get; set; }
}
public abstract class Control : IChildControl //such as a button or radio button
{
ParentControl IChildControl.Parent { get; set; }
}
The explicit implementation (IChildControl.Parent) means that consumers with just a Control instance will not see the Parent property. It must be explicitly cast to IChildControl to access it.
I want to implement access control for usercontrols depending on user role(s), I want to do it on the control base class, in such way that on every user control I only need to set a string with allowed roles to see the user control
This is how an user control class may look like:
public partial class SimpleMenu : MyUsrControlBase
{
protected void Page_Load(object sender, EventArgs e)
{
AlloweRoles = "RoleA, RoleB"
//specific user control functionality
}
}
The base class:
public abstract class MyUsrControlBase : UserControl
{
private string _allowedRoles;
protected internal string AllowedRoles
{
set
{
_allowedRoles = value;
ValidateRoles();
}
}
private ValidateRoles()
{
//Role validation logic
if (RoleHasAccess)
{
// Set user control visibility to true
}
else
{
// Set user control visibility to false
}
}
}
How to set up user control visibility from the base class depending on the validation result?
Also which event in the user control is the best to set the roles?
AlloweRoles = "RoleA, RoleB"
You can set the inherited Visible property from the base class:
private void ValidateRoles()
{
// Role validation logic.
Visible = RoleHasAccess;
}
EDIT: Concerning your second question, you can initialize the AllowedRoles property in the derived class' constructor, so it will be set for the whole lifespan of the user control:
public partial class SimpleMenu : MyUserControlBase
{
public SimpleMenu()
{
AllowedRoles = "RoleA, RoleB";
}
}
I have created a class called BasePage which inherits System.Web.UI.Page. On this page I've declared a property called UserSession which I want to be able to access from any Page/MasterPage.
public class BasePage : System.Web.UI.Page
{
string UserSession { get; set; }
public BasePage()
{
base.PreInit += new EventHandler(BasePage_PreInit);
}
private void BasePage_PreInit(object sender, EventArgs e)
{
UserSession = "12345";
}
}
My Default.aspx.cs page inherits the BasePage class and allows me to access the UserSession property as expected.
public partial class Default : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(UserSession);
}
}
However, even though Default.aspx has MasterPage.Master assigned correctly, when I try and access the UserSession property from MasterPage.Master.cs it can't find it and won't build.
So what am I trying to achieve by doing this? I want to expose a UserSession object to every page in my application. Pretty simple you would have thought? Nope.
MasterPage is separate in the heirarchy to Page so you cannot access the property directly from that. However, MasterPage does have a Page property that returns the Page object, which you can cast to your BasePage class. Then as long as UserSession is public (or internal, or protected internal, which might make good sense here) it can access that property. Unless you've only one master page codebehind, you may want to similarly create a BaseMasterPage and do something like:
public BaseMasterPage : MasterPage
{
protected string UserSession
{
get
{
return (Page as BasePage).UserSession;
}
set
{
(Page as BasePage).UserSession = value;
}
}
}
It is simple. Declare your string variable as public.
EDIT: TheGeekYouNeed's answer is correct... I should know better than to try to answer questions this early on a Monday.
I think you'll need to create a base master page class which holds your UserSession property. This would allow you to access the property from the masterpage as well as the pages that inherit from it.
In ASP.Net Web Forms there are cases that I've come across that create order dependent code. As an obvious code smell I'm looking for solutions to solve this problem.
A pseudo-code example would be:
Calling Code :: Page.aspx
protected void Page_Load(...) {
var control = LoadControl("ControlX.ascx");
// Ugly since the control's constructor is not used by LoadControl
control.SetDependencies(...);
}
Control Code :: ControlX.ascx
public void SetDependencies(...) {
}
protected void Page_Load(...) {
if (dependencies are null)
throw Exception();
else
ContinueProcessing();
}
LoadControl has two signatures, the one used above accepts a string for the control classes physical location and correctly creates the child controls. Whereas the second signature accepts the control class as a class type, and any parameters for the constructor, however the child controls are not created as detailed in TRULY Understanding Dynamic Controls.
So how can I eliminate this order dependency in the cleanest way? My first thought is that if I dynamically created the child controls in ControlX, but then that can be cumbersome for larger controls. Thoughts?
(I hope in understood the problem correctly) You could invert the dependecy like this:
The host of ControlX.ascx (either another control or a page) must implement a certain interface (defined by ControlX). ControlX can then access its dependencies from its host through that interface.
A small example would be this:
public interface IControlXHost
{
// methods, properties that allow ControlX to access its dependencies
int GetStuff();
}
public partial class ControlX : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
var host = (Parent as IControlXHost) ?? (Page as IControlXHost);
if (host == null) {
throw new Exception("ControlX's parent must implement IControlXHost");
}
else {
int number = host.GetStuff();
}
}
}
The host (the page or the control hosting ControlX) would then have to implement that interface, e.g:
public partial class Default4 : System.Web.UI.Page, IControlXHost
{
public int GetStuff() {
return 33;
}
protected void Page_Load(object sender, EventArgs e) {
var control = LoadControl("ControlX.ascx");
}
}
IMO, this approach makes controls easier reusable, since they "automatically" tell you about the requirements that have to be fulfilled to host the control. You don't have to find out which methods of the control you have to call in which order.
i am working on a project, with a set of usercontrols beeing loaded dynamically think about sort of a portal page with a bunch of widgets (blocks) and all of them are a usercontrol.
they have certain things in common, so i made them all derive from a masterBlock usercontrol
now is there a way to also have some output (in the .ascx) file in common?
anything i put in the ascx of the masterBlock is not rendered or overwritten by the derived block.
i was wondering if anyone has any hints to get this to work.
The *.ascx files can not be derived (maybe with some "magic" can). Derived can be only classes, sou you can create a MyUserControlBase class, which can create some common controls/output and provide it by protected/public properties to derived class (MyWeatherUserControl for example) which can common controls/output modify.
Sample code:
public class MyUserControlBase : UserControl {
private Panel mainPanel;
protected Panel MainPanel {
get { return this.mainPanel; }
}
public MyUserControlBase() {
this.mainPanel = new Panel();
this.Controls.Add( this.mainPanel );
this.CreateMainPanelContent();
}
protected virtual void CreateMainPanelContent() {
// create default content
Label lblInfo = new Label();
lblInfo.Text = "This is common user control.";
this.MainPanel.Controls.Add( lblInfo );
}
}
public class MyWeatherUserControl : MyUserControlBase {
protected override void CreateMainPanelContent() {
// the base method is not called,
// because I want create custom content
Image imgInfo = new Image();
imgInfo.ImageUrl = "http://some_weather_providing_server.com/current_weather_in_new_york.gif";
this.MainPanel.Controls.Add ( imgInfo );
}
}
public class MyExtendedWeatherUserControl : MyWeatherUserControl {
protected override void CreateMainPanelContent() {
// the base method is called,
// because I want only extend content
base.CoreateMainPanelContent();
HyperLink lnkSomewhere = new Hyperlink();
lnkSomewhere.NavigationUrl = "http://somewhere.com";
this.MainPanel.Controls.Add ( lnkSomewhere );
}
}
You could override the Render method in the base class to give you custom rendering, and then the subclasses could work with that.