Web Controls within UserControl null? - c#

I've built a small User Control which is essentially a DropDownList with some preset Values based on what the Target-Property is set on.
Here's the Code:
public partial class Selector : System.Web.UI.UserControl
{
public string SelectedValue { get {return this.ddl.SelectedValue; } }
public int SelectedIndex { get { return this.ddl.SelectedIndex; } }
public ListItem SelectedItem { get { return this.ddl.SelectedItem; } }
private string target;
public string Target { get { return this.target; } set { this.target = value; } }
protected void Page_Load(object sender, EventArgs e)
{
ddl.DataSource = target=="Group"?Util.GetAllGroups(Session["sessionId"].ToString()):Util.GetAllUsers(Session["sessionId"].ToString());
ddl.DataBind();
}
}
ASP-Markup:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="Selector.ascx.cs" Inherits="InspireClient.CustomControls.Selector" %>
<asp:DropDownList runat="server" ID="ddl">
</asp:DropDownList>
If I insert my Selector into an aspx-Page it works just fine.
Example:
<SCL:Selector Target="Group" runat="server" />
However, If I programmatically add it like this
ctrl = new Selector();
ctrl.Target = "User";
the DropDownList "ddl" is null and the application (logically) throws an error. Is Page_Load the wrong Method to do such a thing? What am I doing wrong?
I should add, "ctrl" is of type dynamic, not sure if this has anything to do with it.
Thanks in advance!
Dennis

Since you're dynamically adding a user control and not a "simple" web control, you should use the LoadControl() method to instantiate it:
protected void Page_Load(object sender, EventArgs e)
{
Selector yourControl = (Selector) LoadControl("Selector.ascx");
yourControl.Target = "User";
Controls.Add(yourControl);
}

Related

Databind or pass object to web user control property .net

I'm honestly not sure if databinding is the correct technique to achieve this, so if anyone could enlighten me I would be most grateful.
Basically what I'm trying to do is pass an object from the current page into a web user control as such (code simplified):
ExamplePage.aspx
<div>
<EC:AttachmentsView ID="AttachmentsView1" Attachments=<%# this.PageAttachments %> runat="server" />
</div>
ExamplePage.aspx.cs
public partial class ExamplePage : ProductBase
{
private LinkItemCollection _pageAttachments;
public LinkItemCollection PageAttachments
{
get { return _pageAttachments; }
}
public ExamplePage()
{
this.Load += new EventHandler(this.Page_Load);
}
protected void Page_Load(object sender, EventArgs e)
{
// Accessing and assigning attachments (EPiServer way)
_pageAttachments = CurrentPage["Attachments"] as LinkItemCollection ?? new LinkItemCollection();
}
}
The attachments view control has setters and getters for the Attachment and Label properties.
AttachmentsView.ascx.cs
namespace Example.Controls
{
[ParseChildren(false)]
public partial class AttachmentsView : EPiServer.UserControlBase
{
private string _label;
public string Label
{
get { return _label; }
set { _label = value; }
}
private LinkItemCollection _attachments;
public LinkItemCollection Attachments
{
get { return _attachments; }
set { _attachments = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (_attachments == null)
{
_attachments = CurrentPage["DefaultAttachments"] as LinkItemCollection ?? new LinkItemCollection();
}
}
}
}
I'm at the stage where I would expect the page attachments from the ExamplePage to be passed into the AttachmentsView control but the _attachments property is null.
Is what I'm trying to do possible? Is databinding the right technique, if so does anyone know material which explains the concepts easier than the horrible MSDN documentation?
I know I can probably achieve this by programmatically rendering the control but I'd like to try this method first.

How to access value of usercontrol in asp.net

I have a web application that assigns time duration to students in a day. kind of a scheduler.
so for this i have a user control as TimePeriod and this control is loaded dynamically on the web page.
But the number of that user control on a page varies so for this i have user a code that dynamically creates a list of user control.
For example purpose i have set i value up to 2, actually it varies
Looks like this:
for(int i=0;i<2;i++)
{
TimePeriod ib = (TimePeriod)LoadControl("TimePeriod.ascx");
//ib.RightArrowImgUrl = "~/images/wcm-circle-arrow-button.png";
span_tempList.Controls.Add(ib);
}
When user is done making changes for time for all days. i.e. in all user control on page.
the page has a button which takes this changes to database.
but the problem arises here that How to access the values of these text boxes values from the page as it has now been rendered as html.
This is my User Control Code:---
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="TimePeriod.ascx.cs" Inherits="ClassManagment.TimePeriod" %>
<div>
<asp:TextBox ID="time3" size="10" value="08:00" runat="server"></asp:TextBox><asp:TextBox ID="time4" size="10" value="09:00" runat="server"></asp:TextBox>
</div>
Code Behind of usercontrol:--------
public partial class TimePeriod : System.Web.UI.UserControl
{
protected global::System.Web.UI.WebControls.TextBox time3 = new System.Web.UI.WebControls.TextBox();
protected global::System.Web.UI.WebControls.TextBox time4 = new System.Web.UI.WebControls.TextBox();
public string TimeFrom
{
get { return time3.Text; }
set { time3.Text = value; }
}
public string TimeTo
{
get { return time4.Text; }
set { time4.Text = value; }
}
}
How i can access values of usercontrol ?
like so:
TimePeriod ib = (TimePeriod)LoadControl("TimePeriod.ascx");
string timeTo = ib.TimeTo;
string timeFrom = ib.TimeFrom;
On the button click handler, you can have something like this
string timeFrom = null;
string timeTo = null;
foreach (Control control in span_tempList.Controls)
{
if (control is TimePeriod)
{
timeFrom = ((TimePeriod)control).TimeFrom.Text;
timeTo = ((TimePeriod)control).TimeTo.Text;
// Do something with these values
}
}
Keep a global array of your dynamically generated user controls in your class and access those stored instances directly as such:
public partial class Foo : System.Web.UI.Page
{
TimePeriod [] timePeriodArray = new TimePeriod[2];
protected void Page_Load(object sender, EventArgs e)
{
for(int i=0;i<2;i++)
{
TimePeriod ib = (TimePeriod)LoadControl("TimePeriod.ascx");
span_tempList.Controls.Add(ib);
timePeriodArray[i] = ib;
}
}
then you can access those instances directly.

How to access user control properties from page?

I am having problem in accessing user control properties from page.
I have usercontrol on master page with some properties,but i am unable to access them from the codebehind of the page which uses that master page.i want to set some properties of usercontrol on page load.Can anyone suggest how can i access them from page.
E.G.
User Control
ucTabSystem.ascx has following properties:
public string TabName
{
get { return _tabName; }
set { _tabName = value; }
}
public string TabUrl
{
get { return _tabUrl; }
set { _tabUrl = value; }
}
Master Page
InHouseTPAMaster.master has this user control in it.
ClaimHomePage.aspx
Uses Master page InHouseTPAMaster.master and i want to set usercontrol properties in page load of this page.
You can use two methods.
The first is by using Page.Master.FindControl('controlID'). Then you can cast it to the type of your user control. The second method is by adding a <%# MasterType VirtualPath="" TypeName=""%> tag to your aspx page. In the VirtualPath add the virtual path to the master page, and the class in the TypeName. You can then access everything with intellisense
You can try this way to set your properties...
<%# Register TagPrefix="Tab" TagName="sys" Src="ucTabSystem.ascx" %>
<tab:sys id="mysys" runat="server" TabName="xxxxx" TabUrl = "yyyy" />
You need to define a public interface with two properties - TabName and TabUrl in separate code file.
public interface IUserControl
{
string TabName{get;set;}
string TabUrl {get;set;}
}
Implements the IUserControl interface to UserControl class. For instance, I've MyUserControl and its code-behind is:
public partial class MyUserControl : System.Web.UI.UserControl , IUserControl
{
public string TabName
{
get { return ViewState["TabName"] == null ? string.Empty : ViewState["TabName"].ToString(); }
set { ViewState["TabName"]= value; }
}
public string TabUrl
{
get { return ViewState["TabUrl"] == null ? string.Empty : ViewState["TabUrl"].ToString(); }
set { ViewState["TabUrl"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
Register MyUserControl in MasterPage and it has following markup in it.(master page)
<%# Register src="MyUserControl.ascx" tagname="MyUserControl" tagprefix="uc1" %>
......
<uc1:MyUserControl ID="MyUserControl1" runat="server" />
In Page_Load event (or any other) handler of aspx page (Which is a content page of said master page).
protected void Page_Load(object sender, EventArgs e)
{
IUserControl control = Master.FindControl("MyUserControl1") as IUserControl;
control.TabName = "Something";
control.TabUrl = "http://www.example.com";
}

Accessing usercontrols in code-behind in ASP.NET

This question is for an ASP.NET guru. Its driving me nuts.
I have inherited an ASP.NET Web Forms application. This application uses a complex
structure of nested user controls. While complex, it does seem necessary in this case.
Regardless, I have a page that uses a single UserControl. We will call this UserControl
root control. This UserControl is defined as follows:
widget.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="widget.ascx.cs" Inherits="resources_userControls_widget" %>
<div>
<asp:Panel ID="bodyPanel" runat="server" />
</div>
widget.ascx.cs
public partial class resources_userControls_widget : System.Web.UI.UserControl
{
private string source = string.Empty;
public string Source
{
get { return source; }
set { source = value; }
}
private string parameter1 = string.Empty;
public string Parameter1
{
get { return parameter1; }
set { parameter1 = value; }
}
private DataTable records = new DataTable();
public DataTable Records
{
get { return records; }
set { records = value; }
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
UserControl userControl = LoadControl(source) as UserControl;
if (parameter1.Length > 0)
userControl.Attributes.Add("parameter1", parameter1);
bodyPanel.Controls.Add(userControl);
}
private void InsertUserControl(string filename)
{
}
}
In my application, I am using widget.ascx in the following way:
page.aspx
<uc:Widget ID="myWidget" runat="server" Source="/userControls/widgets/info.ascx" />
page.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
DataTable table = GetData();
myWidget.Records = table;
}
Please notice how info.ascx is set as the UserControl we want to load in this case. This approach is necessary in this case. I've removed the extraneous code that justifies it to focus on the problem. Regardless, in info.ascx.cs I have the following:
info.ascx.cs
protected void Page_Load(object sender, EventArgs e)
{
// Here's the problem
// this.Parent.Parent is a widget.ascx instance.
// However, I cannot access the Widget class. I want to be able to do this
// Widget widget = (Widget)(this.Parent.Parent);
// DataTable table = widget.Records;
}
I really need to get the value of the "Records" property from the Parent user control. Unfortunately, I can't seem to access the Widget class from my code-behind. Are there some rules about UserControl visibility at compile time that I'm not aware of? How do I access the Widget class from the code-behind of info.ascx.cs?
Thank you!
Firstly you need to create an interface and implement it to the Widget user control class.
For instance,
public interface IRecord
{
DataTable Records {get;set;}
}
public partial class resources_userControls_widget : System.Web.UI.UserControl, IRecord
{
...
}
And in code behind of Info.ascx.cs,
protected void Page_Load(object sender, EventArgs e)
{
// Here's the problem
// this.Parent.Parent is a widget.ascx instance.
// However, I cannot access the Widget class. I want to be able to do this
// Widget widget = (Widget)(this.Parent.Parent);
// DataTable table = widget.Records;
IRecord record=this.Parent.Parent;
DataTable table = widget.Records;
}
In your case, maybe better to use some server object's like ViewState or Session. Fill it within DataTable on your page and get it in Page_load event handler on info.ascx user control.

EventHandlers of dynamic controls created in a ListView are not fired, if the ListView is bound in Page_Load

In our intranet ASP .NET application we use an architecture approach which is similar to the MVVM pattern.
Our viewmodel, which describes the state of the view, is either created or loaded in Page_Load from the ViewState.
Depending on the viewmodel content the page then is dynamically created.
Right now I am facing a problem where I cannot find an elegant solution.
The problem is that we have to handle events that are fired by the controls, which are dynamically created in the ListView. However, those registered events do only fire, if the listView is databound in Page_Init. If the databinding takes place in Page_Load those events are not fired.
The thing now is, that we need our ViewModel in order to databind the ListView to it. This ViewModel is cached in the ViewState, which - to my knowledge - only comes accessible in Page_Load. That means that in Page_Init we cannot access the ViewModel.
I created the following example:
ASP:
<form id="form1" runat="server">
<asp:ListView runat="server" ID="lstView" ItemPlaceholderID="itemPlaceHolder">
<LayoutTemplate>
<asp:PlaceHolder runat="server" ID="itemPlaceHolder" />
</LayoutTemplate>
<ItemTemplate>
<asp:DropDownList runat="server" ID="dropDown" SelectedValue='<%# Bind("SelectedValue") %>' DataSource='<%# Eval("Choice") %>' AutoPostBack="true" />
</ItemTemplate>
</asp:ListView>
</form>
Code Behind:
namespace WebApplication1
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
//if i put the Initialization logic here, the event gets fired, however the Model is not accessible from the viewstate
}
protected void Page_Load(object sender, EventArgs e)
{
InitializeModel();
lstView.DataSource = _model.NestedModels;
lstView.ItemCreated += (k, args) =>
{
var dropDown = (DropDownList)args.Item.FindControl("dropDown");
dropDown.SelectedIndexChanged += new EventHandler(dropDown_SelectedIndexChanged);
};
lstView.DataBind();
}
void dropDown_SelectedIndexChanged(object sender, EventArgs e)
{
Response.Write("Selected Index Changed fired");
}
private MyModel _model;
void InitializeModel()
{
if (ViewState["model"] == null)
ViewState["model"] = new MyModel();
_model = (MyModel) ViewState["model"];
}
}
[Serializable]
public class MyModel
{
[Serializable]
public class NestedModel
{
public NestedModel()
{
Choice = new List(new[] { "Value1", "Value2", "Value3", "Value4", "Value5" });
}
public string SelectedValue { get; set; }
public List Choice { get; set; }
}
private List _nestedModels = new List();
public MyModel()
{
Init();
}
public List NestedModels
{
get { return _nestedModels; }
}
void Init()
{
NestedModels.Add(new NestedModel() {SelectedValue = "Value1"});
NestedModels.Add(new NestedModel() { SelectedValue = "Value2" });
NestedModels.Add(new NestedModel() { SelectedValue = "Value3" });
NestedModels.Add(new NestedModel() { SelectedValue = "Value4" });
NestedModels.Add(new NestedModel() { SelectedValue = "Value5" });
}
}
}
I hope one of you guys knows a way either to preserve my event to get fired or to retrieve my cached ViewModel in Page_Init.
Best Regards,
TH
You have to override the CreateChildControls event and dynamically add the control there on page postback. This will be called first and then your dynamically event handler is called.
protected override void CreateChildControls()
{
PopulateControls();//populate your controls here
}

Categories