How can I append some html to a div with a specific class name?
frontend:
<div class="school-team-popup"></div>
backend:
StringBuilder _html = new StringBuilder();
_html.AppendFormat("<li>Hi there</li>");
I would like to append _html inside the school-team-popup div. How can I do this from the backend?
I'm going to explain the Web Forms way of doing things.
If you have some static markup that you want to selectively show/hide on your page, that's generally accomplished by setting the Visible property of the control.
<%-- This is in your ASPX markup (.aspx) --%>
<asp:Panel runat="server" id="HelloWorldPanel">
<p>Hello, world!</p>
</asp:Panel>
//This is in your code behind (.aspx.cs)
//hide the panel
HelloWorldPanel.Visible = false;
//show the panel
HelloWorldPanel.Visible = true;
If you're trying to grab dynamic data from some other source and display it on the page, you would declare the markup on your page to show this data, and then bind the data to the markup. There are many controls you can bind data to.
One example of a control you can bind data to is a repeater. Repeaters are good when you want tight control over the markup that gets rendered on the page. You bind them to some enumerable object such as a List<T> and then it will repeat some markup for each element in the enumerable object.
//This is in your project somewhere
namespace MyNamespace
{
public class Product
{
public int Id { get; set; }
public int Name { get; set; }
}
}
<%-- This is in your ASPX markup (.aspx) --%>
<ul>
<asp:Repeater runat="server" id="ProductRepeater" ItemType="MyNamespace.Product">
<ItemTemplate>
<li><%#: Item.Id %> - <%#: Item.Name %></li>
</ItemTemplate>
</asp:Repeater>
</ul>
//this is in your code behind (.aspx.cs)
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostback)
{
List<Product> products = MyDataLayer.GetProducts();
ProductRepeater.DataSource = products;
ProductRepeater.DataBind();
}
}
Related
I have a list of button names and uri's containing links to other pages in my website. This is stored in my database. I also have a javascript function that can create buttons dynamically preferably when the page loads. Now what I need is on the server side to iterate through the list of button names and create a button for every button in the list?
Is this possible. I was thinking of maybe using the string builder to build some html to create the buttons or the method I like more is to call the javascript everytime I need a new button.
Here is my javascript function:
function createHref(Name, Uri) {
var leftDiv = document.createElement("div"); //Create left div
leftDiv.id = "left"; //Assign div id
leftDiv.setAttribute("style", "float:left; width:66.5%; line-height: 26px; text-align:left; font-size:12pt; padding-left:8px; height:26px;"); //Set div attributes
leftDiv.style.background = "#FF0000";
a = document.createElement('a');
a.href = Uri;
a.innerHTML = Name
leftDiv.appendChild(a);
document.body.appendChild(leftDiv);
}
Since this is ASP.NET I would use a Repeater and set the datasource to the button data you pull from your database.
For examples sake, I will assume you have a custom object MyButton that maps to your data:
public class MyButton
{
public MyButton()
{}
public string Name { get; set; }
public string Href { get; set; }
}
You would then have some markup for the repeater:
<asp:Repeater ID="rptMyButtons" runat="server" OnItemDataBound="rptMyButtons_ItemDataBound">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="hypUrl" runat="server" />
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
You would then bind your data to the repeater and set some properties on the objects:
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
rptMyButtons.DataSource = //your data from the database
rptMyButtons.DataBind();
}
}
protected void rptMyButtons_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
{
MyButton button = (MyButton)e.Item.DataItem;
HyperLink hypUrl = (HyperLink)e.Item.FindControl("hypUrl");
hypUrl.Text = button.Name;
hypUrl.NavigateUrl = button.Href;
}
}
It seems like you may be trying to build a sitemap?
I have a list of button names and uri's containing links to other pages in my website
Which is why I have used a <ul> and <li>'s to contain your buttons in a list which makes more sense. It is quite easy to change this back to a <div> however.
I'm using an asp repeater to display a list of names and I want to display the current letter as a type of grouping header, like in an index page.
The data is sorted alphabetically before binding, but i'm finding it difficult to insert the 'A' and 'B' before the names are displayed.
Add a Panel control to your ItemTemplate with visibility set to False. When you are binding the repeater (assuming you are subscribing to the ItemDataBound event), run a check to see if the first letter has changed. If it has, set the panel's visibility to true and print out the letter.
Let me know if you need some example code.
EDIT: EXAMPLE CODE
For clarity sake, "AlphaHeaders" is what we will call the "A", "B", "C" letters that we want to display
aspx code
The Repeater will look like so:
<table>
<asp:Repeater id="rptRepeater" runat="server" OnItemDataBound="rptNames_OnItemDataBound">
<ItemTemplate>
<asp:Panel id="pnlAlphaHeader" runat="server" visible="False">
<tr><td><asp:Label id="lblAlphaHeader" runat="server" /></td></tr>
</asp:Panel>
<tr><td><asp:Label id="lblName" runat="server" /></td></tr>
</ItemTemplate>
</asp:Repeater>
</table>
aspx.cs code
First, you need a variable that holds the current AlphaHeader:
private string _AlphaHeaderCurrent = String.Empty;
Then you will do your work on the repeater's OnItemDataBound event:
protected void rptNames_OnItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
if ((e.ItemType==ListItemType.Item) || (e.ItemType==ListItemType.AlternatingItem)) {
string name = e.Item.DataItem("Name").ToString();
//check if the first letter of the current name is new. If it is new, we print out the header
if(!name.StartsWith(this._AlphaHeaderCurrent)) {
this._AlphaHeaderCurrent = name.SubString(1);
((Panel)e.ItemFindControl("pnlAlphaHeader")).Visible = true;
((Label)e.Item.FindControl("lblAlphaHeader")).Text = the._AlphaHeader;
}
((Label)e.Item.FindControl("lblName")).Text = name;
}
}
You sort before you bind.
That is, bind the sorted result set.
Without seeing the values you have, however, it is not possible to tell exactly how to do so.
Update - from your comment, I would say you need to change your binding source to something like Dictionary<string,IList<string>>.
With such a structure, you could bind by key (sorted) and sublist (secondary sort).
You need to sort your data before bind it to the repeater.
You can use nested repeaters (repeater inside repeater). Like category and subcategory.
In first repeater you can list all your names and make a condition starts with A. Then in sub repeater you can show all names. You will also use itemdatabound event to bind second repeater.
<asp:Repeater id="rptFirstLetters" runat="server" OnItemDataBound="rptChars_OnItemDataBound">
<ItemTemplate>
<div>"<%#Eval("letters") %>"
<asp:Repeater id="rptNames" runat="server">
<ItemTemplate>
<%#Eval("names") %>
</ItemTemplate>
</asp:Repeater>
</div> // bind all letters
</ItemTemplate>
Not really a nice way of doing this to be honest, repeaters generally result in ugly code I've found. The hierarchical approach from kad1r is probably the nicest if you can set it up, but there are alternatives, depending on your implementation details; I kind of prefer this in some ways as it keeps the markup very clean, and as I have a non-programmer design guy that is a plus for me.
ASPX:
<%# Page language="C#" Src="test.CODE.cs" Inherits="test_Page" %>
<asp:Repeater ID="TestRepeater" runat="server">
<ItemTemplate>
<asp:PlaceHolder Visible='<%# Eval("IsFirstInGroup") %>' runat="server">
<strong><%# Eval("Initial") %></strong><br/>
</asp:PlaceHolder>
<%# Eval("Name") %><br/>
</ItemTemplate>
</asp:Repeater>
CODE BEHIND:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public class test_Page : Page
{
protected Repeater TestRepeater;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
String[] names = new String[]
{
"Alpha, John",
"Altman, Mary",
"Asher, Cyril",
"Bachman, Turner",
"Beta, Rob",
"Bexman, Norah",
"Clark, Freddy"
};
List<_DispItem> l = new List<_DispItem>();
for (int i = 0; i < names.Length; i++)
l.Add(new _DispItem() { Name = names[i], IsFirstInGroup = (i == 0 || names[i - 1][0] != names[i][0]) });
TestRepeater.DataSource = l;
TestRepeater.DataBind();
}
private class _DispItem
{
public String Name { get; set; }
public String Initial { get { return Name.Substring(0, 1); } }
public bool IsFirstInGroup { get; set; }
}
}
I have 2 user controls in an ASPX page. By default the second user control should be disabled. In that user control i am having only one text box. So i find the control in the page load event like this:
TextBox txtLocation = (TextBox)PI_CompLocationTree.FindControl("txtLocation");
txtLocation.Enabled = false;
But i am getting txtLocation as null. How do I get the control in the ASPX page from the ASCX control?
My Updated Code..In Aspx page..
<%# Register Src="~/UserControl/PI_CompLocationTree.ascx" TagName="PI_CompLocationTree"
TagPrefix="uc1" %>
<div id="Div2">
<div class="location">
<div class="usLocation">
<uc1:PI_CompLocationTree ID="PI_CompLocationTree1" runat="server"/>
</div>
</div>
</div>
In Page Load...
PI_CompLocationTree PI_CompLocationTree = new PI_CompLocationTree();
protected void Page_Init(object sender, EventArgs e)
{
var userControl = (PI_CompLocationTree)this.FindControl("PI_CompLocationTree1");
userControl.EnabledTextBox = false;
}
In ASCX Page...
<asp:TextBox ID="txtLocation" CssClass="fadded_text fadded_text_ctrl" Style="width: 260px;
float: left;" runat="server" Text=""></asp:TextBox>
In ASCX Code Behind...
public partial class PI_CompLocationTree : System.Web.UI.UserControl
{
public bool EnabledTextBox
{
get { return txtLoc.Enabled; }
set { txtLoc.Enabled = value; }
}
}
Use FindControl Methods as Follow..
1. UserControlClass objOfUserControl = (UserControlClass)Page.FindControl("UserControlID");
TextBox txtLocation= objOfUserControl.FindControl("txtLocation");
txtLocation.Enabled = false;
2.You Can Also use Public Property as Follow
In User Control Codebehind
public bool TextBoxUSC
{
set{txtLocation.Enabled = value;}
}
In Aspx Code Behind
UserControlClass.TextBoxUSC=false;
If You are using Master Page
ContentPlaceHolder cph = (ContentPlaceHolder)this.Page.Master.FindControl("MainContent");//"MainContent" is ContentPlaceHolder's ID
UserControlClass userCntrl = (UserControlClass)cph.FindControl("UserControlID");
userCntrl.TextBoxUSC = false;
Try this
Edited
Make Enabled false in aspx you can make like this:
Add property to your UC:
public bool EnabledTextBox
{
get{return IdTextBox.Enabled;}
set{IdTextBox.Enabled=value;}
}
then in aspx:
IdOfYourUserControlWithProperty.EnabledTextBox = false;
Hope it helps
Robin You can delete
TextBox txtLocation = (TextBox)PI_CompLocationTree.FindControl("txtLocation");
txtLocation.Enabled = false;
In your aspx, add forms with runat="server"
Delete also
PI_CompLocationTree PI_CompLocationTree = new PI_CompLocationTree();
You don't need because you use FindControl
Your work is good
PI_CompLocationTree1.EnabledTextBox = false; //from .aspx page. There's no need to use FindControl if you've added it statically to the webpage.
I'm trying to use the repeat without binding it to a datasource, is this possible?
<asp:Repeater runat="server" ID="rptPageNav">
<ItemTemplate>
<asp:HyperLink runat="server" CssClass="pageLink" ID="pageLink">#</asp:HyperLink>
</ItemTemplate>
</asp:Repeater>
Then in my code, I want to loop through adding the repeater item template for each link available.
for (int i = 0; i < thisTemplate.specification.pagination; i++)
{
}
So the end results should be something like:
<a class="pageLink" href="#">1</a>
<a class="pageLink" href="#">2</a>
<a class="pageLink" href="#">3</a>
<a class="pageLink" href="#">4</a>
Alternatively, if you want only single simple link you don't need Repeater IMO you can have simple Panel then create the links on the fly:
for (int i = 1; i < 5; i++) {
HyperLink link = new HyperLink();
link.CssClass = "pageLink";
link.NavigateUrl = "#";
link.Text = i.ToString();
MyPanel.Controls.Add(link);
}
Create an array of integers up to what you need and bind that to your repeater, using the value as the text for your hyperlink.
No, you have to bind a Repeater to some kind of datasource. Try using an array of ints as #Paddy suggests.
Incidentally, you'll need to modify the markup within the <ItemTemplate> tags to get your hyperlinks to display one above the other as in your example.
MSDN defines asp:Repeater as
A data-bound list control that allows
custom layout by repeating a specified
template for each item displayed in
the list.
Which essentially means we have to bind it to a datasource. Why dont you try and implemt something like this
Markup
<asp:Repeater runat="server" ID="rptPageNav">
<ItemTemplate>
<asp:HyperLink ID="pageLink" runat="server" CssClass="pageLink" NavigateUrl='<%# Eval("Link") %>'><%# Eval("Title") %></asp:HyperLink>
</ItemTemplate>
</asp:Repeater>
Code
public partial class Repeater : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<URL> urls = new List<URL>()
{
new URL(){ Link = "http://www.google.com", Title = "Google"},
new URL(){ Link = "http://www.yahoo.com", Title = "Yahoo"}
};
rptPageNav.DataSource = urls;
rptPageNav.DataBind();
}
}
}
public class URL
{
public string Link { get; set; }
public string Title { get; set; }
}
I know how to do this in MVC:
<title> <%= Model.Title %> </title>
I also know how to bind a SQLDataSource or ObjectDataSource to a control on a form or listview.
But how do I render a field from my SQLDataSource or ObjectDataSource directly into the HTML?
You can use the Page.Title property to set the title in code behind.
Once you've run your SelectCommand or equivalent on your data source, just simply assign Page.Title a value from the result set.
Alternately, you can use the aspx page itself, and just inside the html assign a text string, like this:
<title>
<%= dataSource.Select(...) %>
</title>
You can declare a property and set its value using your desired field's value.
Code-behind:
private string myTitle;
protected string MyTitle
{
get { return myTitle; }
set { myTitle = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
MyTitle = "Testing 123!";
}
Markup: <title><%= MyTitle %></title>
In WebForms you still need to use a WebControl that implements DataBinding as the "container" for your fields. For instance, a GridView, Repeater, ListView, FormView or DetailsView. Unfortunately there isn't a WebControl designed specifically for rending just one row or object. So, you have a choice:
Use a Repeater something like this:
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="MyDataSource">
<ItemTemplate>
<%# Eval("MyProperty") %>
</ItemTemplate>
</asp:Repeater>
Another alernative is to not use a DataSource. Instead, add properties to your page and then bind your data to these. For example, in your page codebehind:
public string MyPageProperty
{
get { return _myPageProperty; }
set { _myPageProperty = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
MyPageProperty = "This is some data";
}
You can then do this in your page:
<div>The value is: <%= MyPageProperty %></div>
Hope that helps.