Please consider the following:
code behind:
public void InitiateTable()
{
Controls.Add(new LiteralControl("<table class=\"table table-invoice\" >")); //Line that gave me error
...
Controls.Add(new LiteralControl("</table>"));
}
on my ASP.Net page:
<% InitiateTable(); %>
When I run the code, it gives me an error saying:
The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Can someone please explain what I have done wrong?
Thank you.
Note Changed LiteralControl to Control as suggested in comment.
You cannot modify the controls collection where the container contains <% %> code blocks as the error message tells you. Controls.Add will modify the controls collection. To get around this:
In your aspx page change
<% InitiateTable(); %>
to
<asp:Literal runat="server" id="mytable" />
then in your page load method, add a call to InitiateTable()
then in your InitiateTable() method change your code to something like this:
public void InitiateTable()
{
var literalControlValue = new StringBuilder();
literalControlValue.Append("<table class=\"table table-invoice\" >");
...
literalControlValue.Append("</thead>"));
mytable.Text = literalControlValue.ToString();
}
Controls.Add(new LiteralControl("<table class='table table-invoice'>"));
The issue is when you use Controls you are referencing the Page itself rather than the area you call InitiateTable.
If you're inserting controls into this area, this is what a Placeholder is for:
<asp:Placeholder id="phTable"></Placeholder>
Then in your Page_Load or some other event code:
private void Page_Load(object sender, System.EventArgs e)
{
phTable.Controls.Add(new LiteralControl("<table class=\"table table-invoice\" >"));
phTable.Add(new LiteralControl("</thead>"));
}
Related
I'm trying display lots of properties from a business object on a Web Form. I could of course, create loads of labels and assign all the values in code-behind, but I feel there must be a less verbose way.
What I want is something like an asp:Panel but where you can specify a datasource. It doesn't seem like Panels support any kind of databinding.
What I'd like is something like this
// C#
panel.DataSource = theCompany;
panel.DataBind();
Then:
// ASPX
<asp:Panel runat="server">
Name: <%# Eval("Name") %>
Phone: <%# Eval("Phone") %>
...
</asp:Panel>
..but I can't find anything which will allow me to work in this way.
I thought I might be able to use asp:FormView but this just gives the error "Data source is an invalid type. It must be either an IListSource, IEnumerable, or IDataSource."
A caveat is that I do not want to call a global DataBind() (this has caused us no-end of problems in the past) - I would like the databind to be constrained to a particular part of the page.
It seems you can do this using a Panel, but you have to assign your business object to a page property first, as there's no way to set the business object as a "DataSource" for the panel (as you would for a Repeater control, for instance).
Once the object is assigned as a page property, you can then use the following syntax in the .aspx to access the properties of that object, without needing to manually assign each item to control values in code behind:
<%# Company.Name %>
You don't need to databind (although you can). What you need is a simple expression evaluator. Add a property to your code behind like this
public string Test { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
Test = "<script>alert('test');</script>";
}
Then use it to render code directly to the page like this
The value: <%: Test %>
Note that the <%: syntax escapes the input. If you wish to NOT escape the input then you can use <%= syntax. Note that you don't need to have a string object you can access any properties you like for example
The value lenght: <%: Test.Length %>
Use The below:
<asp:DetailsView runat="server">
Name: <%# Eval("Name") %>
Phone: <%# Eval("Phone") %>
</asp:DetailsView>
Use DetailsView. You can add it from the Toolbox. It's for Single Row Data Presentation.
<asp:DetailsView runat="server">
Name: <%# Eval("Name") %>
Phone: <%# Eval("Phone") %>
</asp:DetailsView>
Why not using DetailsView. Its perfect for what you want. Showing single row of data only and that too in two column form.
I suggest using a standard Repeater, databound with an array containing a single item.
Repeater.DataSource = new [] { theCompany };
Repeater.DataBind();
Advantage over databinding to a Panel: you can still use the ItemType attribute, and have access to the nice strongly typed Item object and don't have to go about using Eval, i.e.:
<asp:Repeater runat="server" Id="Repeater" ItemType="CompanyViewModel">
<ItemTemplate>
Name: <%# Item.Name %>
Phone: <%# Item.Phone %>
</ItemTemplate>
</asp:Repeater>
(Replace "CompanyViewModel" with the Type of your: "theCompany".)
You can also try experimenting with DetailsView, but it's not as malleable as a Repeater.
Create your own user control that shows the properties of the objects. You can use reflection to read property names and values and display in control.
Create a property for your object in your user control. Inside user control code behind write function Show() with below code.
//Build html strin from all propeties
PropertyInfo[] properties = yourObject.GetType().GetProperties();
string lbl = "<label>{0}</label>";
string value= "<span>{0}</span>";
string tab ="\t";
StringBuilder sb = new StringBuilder();
foreach (PropertyInfo pi in properties)
{
var label = string.Format(lbl,pi.Name);
var val = string.Format(value, pi.GetValue(yourObject, null))
sb.Append(label+tab+val);
sb.Append("<br/>")
}
Response.Write(sb.ToString());
Now in your pager add that control and sets its object property in code behind like
myControl.MyObject = yourObject;
myControl.Show();
NickG's answer will work... however consider two scenarios.
If your business object is ever null, the page will crash with an "Object Reference" error. This can be avoided with a cumbersome looking
<% if(MyObject != null) { %><%= MyObject.Prop %><% } %>
... but doing that every time makes for messy code.
If your page uses PostBack processing via UpdatePanel, the business object will have to be reloaded to the property every time the Page lifecycle runs... even if that portion of the page isn't being redrawn. This is because IIS will resolve all the <%= MyObject.Prop %> references regardless, causing wasted CPU cycles and probably wasted database calls if your object is coming from a database.
For these reasons I always use a Repeater control, which is lightweight, supports ViewState, can easily be assigned a one item list, and avoids the aforementioned issues. Here's an example using the HttpContext.Current.Request object as a "business object".
<asp:Repeater ID="rptTest" runat="server">
<ItemTemplate>
Request.URL = <%# Eval("Url") %>
</ItemTemplate>
</asp:Repeater>
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
var objTest = Request; //Using the Request object as a test business object
rptTest.DataSource = new List<System.Web.HttpRequest>() { objTest };
rptTest.DataBind();
}
}
To make this work we can customize ASP.NET Panel by inheriting it and using Custom Server control for ASP.NET
Use Below Code to modify the ASP.NET Panel in an ASP.NET Custom Server Control Project:
[DefaultProperty("Text")]
[ToolboxData("<{0}:CustomPanel runat=server></{0}:CustomPanel>")]
public class CustomPanel : Panel
{
[Bindable(true)]
public object MyDataSource
{
get;
set;
}
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public StringBuilder Text
{
get;
set;
}
public void MyDataBind()
{
Text = new StringBuilder();
foreach (PropertyInfo p in MyDataSource.GetType().GetProperties())
{
Text.Append(string.Format("<b>{0}</b>", p.Name));
Text.Append(":");
if (p.GetIndexParameters() == null || p.GetIndexParameters().Length == 0)
Text.Append(p.GetValue(MyDataSource, null));
Text.Append("<br />");
}
}
protected override void RenderContents(HtmlTextWriter output)
{
output.Write(Text);
}
}
Then add this control's reference and toolbox item to your ASP.NET page:
<cc2:CustomPanel ID="MyCustomPanel" runat="server">
</cc2:CustomPanel>
Use the control as shown below:
MyCustomPanel.MyDataSource = theCompany;
MyCustomPanel.MyDataBind();
I want to change some string located in html file when it loads. For example, i have a html file:
<html>
<head>
<title>MyTitle</title></head>
<body>
Some Text
<script type='text/javascript'>
/*some script*/
var myString = "TargerInfo";
/*some script*/
</script>
</body>
</html>
I use Page_Load method in code-behind file:
protected void Page_Load(object sender, EventArgs e)
{
/*Insert necessary snippet of code*/
}
What code should i use to change string "TargerInfo" to "OtherString" ?
[EDIT]
Sorry, that I have forgot to mention
I can add any info to html page only in code-behind class, because this page isn't generated by me.
I think i should use something like this:
1) load html file
2) find my string
3) replace it
4) send html file
There is an aspx page, but i add only some part of code and other code is added by VS
Unless I'm missing something (because this seems like a bit of an ASP.NET 101), you have several options...
Create a variable in the code-behind and then use that...
protected string _newText = "";
protected void Page_Load(object sender, EventArgs e)
{
_newText = "OtherString";
}
And then in the ASPX...
var myString = "<%=_newText%>";
Otherwise you can use the <asp:Literal> control
UPDATE
After an extensive chat with #andDaviD it turns out that the javascript is in a Master page held in SharePoint Foundation.
The Master page is being referenced in his Content page via the DynamicMasterPageFile attribute in the <%# Page directive, and that is why he said he is able to update some part of the code, but not others.
I am still unsure as to whether it is possible for the Master page to be modified (either by himself or an administrator), that is something he needs to find out from the people in charge at his company. But I believe the adding of a property or method to the Master Page to provide what he needs is the only sensible option.
You could use inline aspx code tags:
<script type='text/javascript'>
/*some script*/
var myString = "<%= getTargetInfo() %>";
/*some script*/
</script>
in codebehind:
protected String getTargetInfo()
{
return "OtherString";
}
You could use a literal:
protected void Page_Load(object sender, EventArgs e)
{
literal.Text = string.Format("var myString = \"{0}\"", targetInfoValue);
}
Markup:
<html>
<head>
<title>MyTitle</title></head>
<body>
Some Text
<script type='text/javascript'>
/*some script*/
<asp:Literal id="literal" runat="server" />
/*some script*/
</script>
</body>
</html>
You can have it in a hiddenfield in asp.net and change the hidden field in code behind.
in your code behind:
public string otherString;
otherString = "some text" //update the string with the value oyu want.
in aspx page put this line in any place you want to see the otherString.
<%=otherString%>
The above is the code in my .aspx page.
How this can be added from code behind dyanmically?
<ul runat="server" id="1">
<li>abc
<ul runat="server" id="2">
<li>3</li>
<li>2</li>
</ul>
</li>
</ul>
you can take the analogy of the tutorial given in this link :
http://neimke.blogspot.com/2011/01/create-delicious-user-interface-for.html
it worked for me - It dynamically adds the list items using the given code below using jquery .. check it pout ...
<li id="tagInputListItem"><input class="tagInput" id="tagInput" /></li>
You can put a PlaceHolder in your .aspx and give it an id, then use that id in code behind page and add controls to that placeholder.
For more information you can see in here.
And if you're really sure about "runat=server" attribute maybe this post of mine it's useful (here)
If you need clarifications give me a feedback.
You must use the "InnerHtml" property of "sidebarmenu1" control.
protected void Page_Load(object sender, EventArgs e)
{
this.loadHtml();
}
So you can generate every list item code and add it to the InnerHtml:
private loadHtml()
{
this.sidebarmenu1.InnerHtml = GetListHtml().ToHtmlString();
}
And a little example for this GetListHtml:
public string GetListHtml()
{
StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.AppendLine("<li>Flat");
htmlBuilder.Append("<ul runat="server" id="sidebarmenu2">");
htmlBuilder.AppendLine("<li>Flat 1`enter code here`</li>");
htmlBuilder.Append("<li>Flat 2</li></ul>");
return htmlBuilder.ToString();
}
This GetListHtml method can call to a DAL or load data from any other place... use a foreach to load every item...
You can use ASP Literal to populate data from back-end code
eg. if you have literal with id ltrNavigation
protected void Page_Load(object sender, EventArgs e)
{
ltrNavigation.text = "";
if (!IsPostBack)
{
ltrNavigation.text += "<ul id='sidebarmenu1'>";
ltrNavigation.text += "<li><a href='#'>Flat</a></li>";
ltrNavigation.text += "</ul>";
}
}
I have a custom .ascx control and would like to set one of it's properties using code. In the .aspx I have this:
<uc1:CustomContent ID="bunchOfContent" runat="server" contentPayload='<%# getRegionID() %>' />
In the codebehind I have:
public partial class Region : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
... things
}
public string getRegionID()
{
//return "region_" + Request["region"];
return "thevalueIwant";
}
However, the value I want is not populated and the code is not invoked (breakpoints are not triggered).
What am I doing wrong? I've tried various changes like changing the quotes from " to ' to no quotes at all. Also I've used <%= instead of <%# but no luck. Thanks!
In the Page_Load method, you can do:
bunchOfContent.contentPayload = getRegionID();
The reason why <%# ... %> did not work is because that's the form you use for databinding. In order for the code you put in there to be executed, you need to call the DataBind() method somewhere. And as for <%= ... %>, that's not suitable for setting a server control property, it simply is a short form of <% Response.Write(...) %>.
I have a simple ASP.NET Web User Control. It looks like this:
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="NewsArticle.ascx.cs"
Inherits="Website.Controls.NewsArticle" %>
<div>
<asp:Literal ID="ltlBody" runat="server" />
</div>
My code behind looks like this:
namespace Website.Controls
{
public partial class NewsArticle : System.Web.UI.UserControl
{
public String bodyText
{
//get { return ltlBody.Text; }
set { ltlBody.Text = value; }
}
}
}
On a .aspx page I have <asp:Panel ID="pNews" runat="server" />
In the code behind I have:
foreach (vwNews news in newsQuery)
{
NewsArticle article = new NewsArticle();
article.bodyText = news.Body;
pNews.Controls.Add(article);
}
Every time I run this code the newsQuery is populated correctly and I get to the line
aticle.bodyText = news.Body; and then I received the error article.bodyText threw an exception of type 'System.NullReferenceException'
I am not sure what is causing this error message or how to fix it. I would think that there should not be an issue. I tried creating a constructor for my Web User Control so that it would give default values to my properties but that didn't work. Any idea how to make this work? It doesn't seem like it should be that
To load a control programatically you need to use the Page.LoadControl() method. See this MSDN article
You have a typo within the code you've written. 'aticle' instead of 'article'.