Public Properties in Code Behind of a User Control - asp.net

In a regular .aspx page, you can access public properties from the codebehind. Is there any way to do a similar thing in a user control. For example, in the following code 'List' is public property of the codebehind of the user control and yet it is not accessible.
<% foreach (TripTeam team in List) { %>
<div>
<label><%= team.Name %></label>
</div>
<%} %>

You can access the public properties of a UserControl from your .aspx page. Here's an example
<script runat="server">
public string Caption { get { return _caption.Text; } set { _caption.Text = value; } }
public string Text{ get { return _tb1.Text; } set { _tb1.Text = value; } }
<div>
<asp:Label ID="_caption" runat= "server" class="caption" /><br />
<asp:TextBox ID="_tb1" runat="server" CssClass="textBox" Width="25px" />
Then on your aspx page, you can set the Text and Caption properties within your user control:
<uc1:CaptionText ID="ct1" runat="server" Caption="User name" />

You need to say 'userControlId.List' to access the property when accessing a property in the control from a page which uses the control.

Related

How to access property defined in code-behind from markup in Web Forms User Control

I have a User control (PlacementUI.ascx) that has a property defined in its code-behind.
//PlacementUI.ascx.cs
public partial class PlacementUI : System.Web.UI.UserControl
{
public PlacementDTO DataItem { get; set; }
}
How can I access that property in the markup ?
tried this but it says DataItem does not exist in the current context
<div class= '<%# DataItem.CssClass %>'>
This is the ugly inline approach:
<div class= '<%# ((PlacementDTO)DataBinder.Eval(Container.DataItem, "DataItem")).CssClass%>'>
other approach, you need to make the div runat=server and give it an ID:
<div runat="server" id="MyDivId">
in codebehind (it is a HtmlGenericControl):
MyDivId.Attributes["class"] = DataItem.CssClass;
You could also use a Panel which is rendered as div.
<asp:Panel id="MyPanel" runat="server" />
codebehind:
MyPanel.CssClass = DataItem.CssClass;

Access ASP.NET Master Page DropDownList Control in the Master Page's Code Behind

I have a master page with a dropdownlist control on it. In the code behind of the said master page, I want to access the dropdownlist control and assign a data source to it. Below is the source code of the master page:
<section id="login">
<asp:LoginView runat="server" ViewStateMode="Disabled">
` <AnonymousTemplate>
<ul>
<asp:Label ID="Label1" runat="server" Text="Report Category"></asp:Label>
<asp:DropDownList ID="CountriesDropDownList" runat="server"></asp:DropDownList>
</ul>
</AnonymousTemplate>
Below is what I want to do in the code behind file.
CountriesDropDownList.DataSource = "myDataSource";
You want to access this dropdownlist on your content page, right?
You could try:
this.Master.CountriesDropDownList.DataSource = "myDataSource";
or check this out: http://msdn.microsoft.com/en-us/library/xxwa0ff0.aspx
Create a string property in master's code behind:
public string CountriesDropDownListDataSource
{
get {
return this.CountriesDropDownList.DataSource;
}
set {
this.CountriesDropDownList.DataSource= value;
}
}
To set the datasource do this:
var myMaster = this.Master as YourMasterType;
if(myMaster != null)
{
myMaster.CountriesDropDownListDataSource = "myDataSource";
}
Or directly from the masterpage
this.CountriesDropDownListDataSource = "myDataSource";

asp:label doesn't render children

I have an asp:label with a nested custom control and it simply doesn't render. I tried to register a custom WebControlAdapter for Label type and while debugging I noticed that there is apparently no control in the Controls collection, it seems to be completely ignoring any nested elements.
Here's markup
<asp:Label ID="lbl13" runat="server" AssociatedControlID="txt13" Text="<%$ Resources:Resources, lbl13 %>">
<asp:ValidationMessage ID="vm13" runat="server" MessageFor="txt13" CssClass="field-validation-error"></asp:ValidationMessage>
</asp:Label>
Any idea how to bypass this problem?
When you set the Text property, it clears the child controls. If you remove the Text="<%$ Resources:Resources, lbl13 %>" from the Label, your child controls should render.
EDIT
If you set the Text property to a static string and add only literal content, the label will only render the literal content:
<asp:Label runat="server" Text="Hello"> World</asp:Label>
Output: World
If you set the Text property to a static string and add child controls, the label will render the text and the child controls:
<asp:Label runat="server" Text="Hello">
<asp:Label runat="server" Text="World" />
</asp:Label>
Output: HelloWorld
If you set the Text property using an expression builder, the label will only render the text:
<asp:Label runat="server" Text="<%$ Resources:Resources,Hello %>">
<asp:Label runat="server" Text="World" />
</asp:Label>
Output: Localised version of "Hello"
To override this behaviour, you'll need a custom Label control. For example:
public class MyLabel : Label
{
public override string Text
{
get { return base.Text; }
set
{
if (HasControls())
{
Controls.AddAt(0, new LiteralControl(value));
}
else
{
base.Text = value;
}
}
}
}

Repeater and public array as NOT datasource.

I want to using two dataSources with repeater. One is binded to dataSource property so my question is is that possible to f.ex. to also repeat some array of string as public property?
It is possible to bind to a property of your datasource that is also a collection. For example:
class Person
{
List<Phone> Phones { get; set; }
string Name { get; set; }
}
class Phone
{
string Number { get; set; }
}
void Page_Load(...)
{
List<Person> people = GetPeople();
peopleRepeater.DataSource = people;
peaopleRepeater.DataBind();
}
aspx page
<asp:Repeater ID="peopleRepeater" runat="server">
<ItemTemplate>
Name : <%# Eval("Name") %>
Phones: <br/>
<asp:Repeater ID="phonesRepeater" runat="server" DataSource='<%# (Container.DataItem as Person).Phones %>'>
<ItemTemplate>
<%# Eval("Number") %> <br />
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
Most ASP.NET Data controls only will bind to a single data source at a time. It is possible to have nested controls that can be bound to multiple data sources. Some 3rd party controls such as RadGridView are designed to handle multiple datasource binding (e.g. hierachical).

Is there any way to declaratively pass code-behind property values to server controls?

Can anyone explain why you can’t use inline code blocks within server control declarations in ASP.Net?
The following is a simple example...
....
<form id="form1" runat="server">
<asp:Label ID="Label1" runat="server" Text="<%= SomeProperty %>"></asp:Label>
</form>
....
The code block is rendered literally to the page...
<span id="Label1"><%= SomeProperty %></span>
My initial thoughts are it has to do with the order that these things are processed in the page life-cycle. The <%=...%> blocks are, as I understand it, equivalent to a Response.Write(...) in code-behind. And since the server control is not actually rendered as declared in the markup, I suppose it may not be possible to process an embedded code block before this rendering takes place.
I would be very grateful of anyone could explain that a little better.
However, the data binding code block <%#...%> is obviously different in the way it behaves, but can anyone tell me why it is possible to embed these within a server control...
....
<asp:Repeater id=Repeater1 runat="server">
....
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval(“SomeProperty”) %>'></asp:Label>
</ItemTemplate>
....
</asp:Repeater>
....
This works fine.
You're mostly right about the <%=...%> syntax.
Here is an example of what happens under the hood:
<script runat="server">
public string SomeProperty { get { return "Hello World!"; } }
</script>
<form id="form1" runat="server">
<%= SomeProperty %>
<div>
<asp:Label ID="Label1" runat="server" Text="<%= SomeProperty %>"></asp:Label>
</div>
</form>
This is parsed and the following C# code is created (I've simplified it a bit):
private Label #__BuildControlLabel1()
{
Label #__ctrl = new Label();
this.Label1 = #__ctrl;
#__ctrl.ApplyStyleSheetSkin(this);
#__ctrl.ID = "Label1";
#__ctrl.Text = "<%= SomeProperty %>";
return #__ctrl;
}
private void #__Renderform1(HtmlTextWriter #__w, Control parameterContainer)
{
#__w.Write( SomeProperty );
#__w.Write("\r\n <div>\r\n ");
parameterContainer.Controls[0].RenderControl(#__w);
#__w.Write("\r\n </div>\r\n ");
}
Here is an example of what happens under the hood for the <%#...%> syntax:
<script runat="server">
public string SomeProperty { get { return "Hello World!"; } }
protected void Page_Load(object sender, EventArgs e) { Label1.DataBind(); }
</script>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" Text="<%# SomeProperty %>"></asp:Label>
</div>
</form>
Generates this code:
private Label #__BuildControlLabel1()
{
Label #__ctrl = new Label();
this.Label1 = #__ctrl;
#__ctrl.ApplyStyleSheetSkin(this);
#__ctrl.ID = "Label1";
#__ctrl.DataBinding += new System.EventHandler(this.#__DataBindingLabel1);
return #__ctrl;
}
public void #__DataBindingLabel1(object sender, EventArgs e)
{
Label dataBindingExpressionBuilderTarget = ((Label)(sender));
Page Container = ((Page)(dataBindingExpressionBuilderTarget.BindingContainer));
dataBindingExpressionBuilderTarget.Text = System.Convert.ToString( SomeProperty , System.Globalization.CultureInfo.CurrentCulture);
}
As you can see the <%=...%> syntax can be used outside of a server control's properties to directly render the returned value. On the other hand the <%#...%> syntax generates a event handler for the DataBinding event of the label. This event sets the value of the label's property to the value of SomeProperty. The DataBinding event fires whenever the DataBind method is called which is why I added that call to the Page_Load event.
Hopefully this will help you understand the difference between them.
You could create a custom ExpressionBuilder so you use something like <%$ Code: SomeProperty %>
You can create a custom databound control, e.g.
namespace FooBar.WebControls
{
public class DataBoundPlaceHolder:PlaceHolder
{
private bool hasDataBound = false;
protected override void CreateChildControls()
{
if (!hasDataBound)
{
this.DataBind();
hasDataBound = true;
}
base.CreateChildControls();
}
}
}
Then wrap your code in this new control, and use the <%# %> syntax, e.g.
<%# Register TagPrefix="WebControls" Namespace="FooBar.WebControls" Assembly="FooBar" %>
<form id="form1" runat="server">
<WebControls:DataBoundPlaceHolder runat="server">
<asp:Label ID="Label1" runat="server" Text='<%# SomeProperty %>'></asp:Label>
</WebControls:DataBoundPlaceHolder>
</form>

Resources