How to Add UserControl Conditionally to Repeater Control? - c#

I want to know how to Add a UserControl Conditionally to a Repeater Control. I have tried to add it to the placeholder which is in Repeater Control but unable to load the usercontrol. This following code doesn't work.
<asp:Repeater ID="ResultsRepeater" runat="server">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<div>
<asp:PlaceHolder ID="PlaceHolder1" runat="server">
</asp:PlaceHolder>
</div>
</ItemTemplate>
</asp:Repeater>
public void GetStatus(int i)
{
UserControl uc = new UserControl();
if(i==1)
{
uc = LoadControl("DraftList.ascx") as UserControl;
}
else if(i==2)
{
uc = LoadControl("FinalList.ascx") as UserControl;
}
PlaceHolder p1 = (PlaceHolder)ResultsRepeater.Items[0].FindControl("PlaceHolder1");
p1.Controls.Add(uc);
}

Is there some reason that you don't want to just handle all of this in the aspx? That would be the simplest and cleanest option:
<asp:Repeater runat="server" ID="ResultsRepeater">
<ItemTemplate>
<uc1:DraftList ID="DraftList1" runat="server" Visible='<%# ((int)Eval("Status") == 1)%>' />
<uc2:FinalList ID="FinalList1" runat="server" Visible='<%# ((int)Eval("Status") == 2)%>' />
</ItemTemplate>
</asp:Repeater>
If a control is not visible, (i.e., Visible=false) then no markup is rendered, so coding in this fashion would not create any more work for the server or the client browser, while having the benefit of being much easier to read and providing user control properties at design-time.
You would just need to make sure to register your controls at the top of the page:
<%# Register src="DraftList.ascx" tagname="DraftList" tagprefix="uc1" %>
<%# Register src="FinalList.ascx" tagname="FinalList" tagprefix="uc2" %>

Why don't you try adding it within the repeaters ItemDataBound event? I.e.,
<asp:Repeater ID="ResultsRepeater" OnItemDataBound="ResultsRepeater_ItemDataBound" runat="server">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<div>
<asp:PlaceHolder ID="PlaceHolder1" runat="server">
</asp:PlaceHolder>
</div>
</ItemTemplate>
</asp:Repeater>
and in the code behind
protected void ResultsRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Panel PlaceHolder1 = (Panel)e.Item.FindControl("PlaceHolder1");
// declare/obtain the value of i given the DataItem
// e.g.,
int i = ((int)e.Item.DataItem); // or however you're getting i
if (i == 1)
{
var uc = LoadControl("~/DraftList.ascx");
PlaceHolder1.Controls.Add(uc);
}
else if (i == 2)
{
var uc = LoadControl("~/FinalList.ascx");
PlaceHolder1.Controls.Add(uc);
}
}
}
Judging by your last comment (to the question) you might need to also make sure you've attached and bound your datasource to the repeater as well. I.e.,
ResultsRepeater.DataSource = dataSource; //whatever your datasource is e.g., datatable, IEnumerable list etc
ResultsRepeater.DataBind();

Related

Get a value from Repeater in code-behind

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="EntityDataSourceTeklifler">
<ItemTemplate>
<div class="panel panel-primary">
<div class="panel-body">
<strong>Teklif Kodu:</strong> <%#Eval("TeklifId") %><br />
<strong>Teklif Tarihi:</strong> <%#Eval("TeklifTarih") %><br />
<strong>Teklifi Hazırlayan:</strong> <%#Eval("Name") %> <%#Eval("Surname") %><br />
<strong>Firma Adı:</strong> <%#Eval("FirmaAdi") %><br />
<strong>Sipariş:</strong> <%#Eval("FUrunId") %><br />
<strong>Teklif Tutarı:</strong> <%#Eval("TeklifTutar") %><br />
</div>
</div>
</ItemTemplate>
</asp:Repeater>
As you can see I have a Repeater and it displays my data without a problem. I need to access TeklifIds in code-behind. I am going to make something like:
if(TeklifId == 1)
{
//do something
}
else if(TeklifId == 2)
{
//do something else
}
And to do this, I need to get all TeklifId while it is adding to the Repeater.
Ideally you should include the data withing some ASP.NET controls like Label, Textbox control within ItemTemplate tag because it is easy to work with them. But I am not sure why you are adding the normal html tags directly.
Anyways, to find the value you will have to find it within the ItemDataBound control of repeater control but for that you will have to make the strong tag a server control by adding runat="server" attrribute like this:-
<strong id="TeklifId" runat="server">Teklif Kodu:</strong> <%#Eval("TeklifId") %>
Then, add the ItemDataBound event in your repeatre control like this:-
<asp:Repeater ID="Repeater1" runat="server" OnItemCommand="Repeater1_ItemCommand"
Finally in the code behind you can find the value like this:-
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem ||
e.Item.ItemType == ListItemType.Item)
{
HtmlGenericControl TeklifId = e.Item.FindControl("TeklifId") as HtmlGenericControl;
string TeklifId = TeklifId.InnerText; //value here
}
}
Place TeklifId in a Label control so that you can use ID and FindControl to get the values like this:
<asp:Label ID="TeklifId" runat="server" Text='<%#Eval("TeklifId") %>'></asp:Label>
And then:
foreach (RepeaterItem item in Repeater1.Items)
{
var TeklifId = (Label)item.FindControl("TeklifId");
if (TeklifId == 1)
{
//do something
}
}
Repeater Code :
<td>
<span runat="server" id="lbBranchname" style="font-style:italic;"><%# Eval("branchname")%></span>
</td>
Code behind : rptBranch_ItemCommand
HtmlGenericControl lbBranchname = e.Item.FindControl("lbBranchname") as HtmlGenericControl;
BranchName = lbBranchname.InnerText;

Binding controls dynamically to PlaceHolder in asp:DataList

I can't seem to figure this one out but I'm trying to add a user control to a DataList at runtime (because the actual control type can differ). So if I hard code the control reference in the markup like this it works:
<asp:DataList ID="myDL" runat="server" RepeatDirection="Horizontal" RepeatColumns="3" OnItemDataBound="myDL_Item_Bound">
<ItemTemplate>
<prefix:MyControl ID="myControl1" runat="server" />
</ItemTemplate>
</asp:DataList>
But if I try to add it programmatically to a placeholder, it does not render the user controls (just empty td tags):
<asp:DataList ID="myDL" runat="server" RepeatDirection="Horizontal" RepeatColumns="3" OnItemDataBound="myDL_Item_Bound">
<ItemTemplate>
<asp:PlaceHolder ID="ph" runat="server">
</asp:PlaceHolder>
</ItemTemplate>
</asp:DataList>
protected void myDL_Item_Bound(Object sender, DataListItemEventArgs e) {
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) {
PlaceHolder ph = (PlaceHolder)e.Item.FindControl("ph");
if (ph != null) {
MyControl ctrl = new MyControl();
ctrl.SomeProp = "xyz";
ph.Controls.Add(ctrl);
}
else {
MyControl ctrl = (MyControl)e.Item.FindControl("myControl1");
ctrl.SomeProp = "xyz";
}
}
}
what am I missing?
You are not adding the control to the page. You need to add it:
Control ctrl = (Control)Page.LoadControl("MyControl.ascx");
// MyControl ctrl = new MyControl();
ctrl.SomeProp = "xyz";
ph.Controls.Add(ctrl);

Validating output from repeater

I'm pretty new in ASP.net, and im trying to validate some output from my SQL DB.
I want to test if "img" from my DB is set to somthing, and if, i wan't to output it.
<asp:SqlDataSource ID="selectFromNews" runat="server" ConnectionString="<%$ ConnectionStrings:DatabaseConnectionString1 %>"
ProviderName="<%$ ConnectionStrings:DatabaseConnectionString1.ProviderName %>"
SelectCommand="SELECT * FROM [news] ORDER BY [time] DESC">
</asp:SqlDataSource>
<asp:Repeater ID="newsRepeater" runat="server" DataSourceID="selectFromNews" onitemcommand="newsRepeater_ItemCommand">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<div class="newsBox">
<h1><%# Eval("title") %></h1>
/* Test if "img" is set to somthing, and output it here, if not, do somthing else */
<p><%# Eval("text") %></p>
</div>
</ItemTemplate>
<FooterTemplate></FooterTemplate>
</asp:Repeater>
I was thinking getting the data from behindcode, and then testing and sending an output back to a Literal, but dont know how i would access the repeaters data from there?
first add image control in Repeater as
<asp:Image ID="ImageID" runat="server" ImageUrl='<%# Eval("img")%>' Visible="false" />
then get this image control in ItemDataBound event of repeater as
protected void YourRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
Image ImageID= e.Item.FindControl("ImageID") as Image;
// now play with your ImageID control..
}
}
Unfortunately the use of <% If ... Else ... End %> blocks within repeaters is not available (trust me, I've wanted them so many times).
The easiest way of doing it is to call a code-behind function. For instance...
protected string MyFunction(RepeaterItem row)
{
// return based on row.DataItem value
return (row.DataItem.ImgExists ? "Image" : "No Image");
}
And then in the markup, you simply pass the Container object...
<%#MyFunction(Container)%>
EDIT... although for more complex visual changes, I would recommend the ItemDataBound solution that Tim and Usman (and Nikhil) provide
You should use repeater's ItemDataBound event:
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem ri = e.Item;
DataRowView dr = (DataRowView)ri.DataItem;
Panel Panel1 = (Panel)ri.FindControl("Panel1");
// do your evaluation here according the values in the DataRowView
// use ri.FindControl("ID") to find controls in the Itemtemplate
}
aspx:
<ItemTemplate>
<asp:Panel id="Panel1" runat="server" class="newsBox">
<h1><%# Eval("title") %></h1>
add controls here with runat=server, then you can find them from codebehind
<p><%# Eval("text") %></p>
</asp:Panel>
</ItemTemplate>

Formatting the output of certain items bound to Repeater

For example in the backend I'm binding a datable to a repeater and in the front end I'm setting up my repeater as such:
<asp:Repeater ID="Repeater1" runat="server" onitemdatabound="Repeater1_ItemDataBound">
<ItemTemplate>
<div class="user">
Name: <%# DataBinder.Eval(Container, "DataItem.Name")%>
Email: <%# DataBinder.Eval(Container, "DataItem.Email")%>
Active: <%# DataBinder.Eval(Container, "DataItem.Active")%>
Status: <%# DataBinder.Eval(Container, "DataItem.Status")%>
</div>
</ItemTemplate>
</asp:Repeater>
So the output for "name" and "email" are fine. However "Active" and "Status" print out an integer code that I would like to change to a more descriptive string based on a reference table I have.
I'm guessing I can do this on the "ItemDataBound" event of the repeater, but I'm stuck on what my next step should be, namely checking the two fields that I need to modify and change them.
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
//Do modifications here
}
}
You can either
Handle the formatting in the ItemDataBound event
Create public methods in your Page or WebUserControl class to handle the formatting.
Using option 1 will require you to declare a control such as a label to store the value for each field like so:
<asp:Repeater ID="Repeater1" runat="server" onitemdatabound="Repeater1_ItemDataBound">
<ItemTemplate>
<div class="user">
<asp:Label ID="ActiveLabel" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.Name")%>'></asp:Label>
</div>
</ItemTemplate>
</asp:Repeater>
Then in your ItemDataBound event you can find the control and set its value as required.
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Label activeLabel = (Label)e.Item.FindControl("ActiveLabel");
//Format label text as required
}
}
Using option 2 will require you to create a server side publicly accessible method which you can call like so:
<asp:Repeater ID="Repeater1" runat="server" onitemdatabound="Repeater1_ItemDataBound">
<ItemTemplate>
<div class="user">
Active: <%# FormatActive((string)DataBinder.Eval(Container, "DataItem.Active")) %>
</div>
</ItemTemplate>
</asp:Repeater>
Then define a method like so:
public string FormatActive(string input)
{
//Format as required
//Return formatted string
}
I prefer creating format methods called in the markup rather than handling ItemDataBound.
<asp:Repeater ID="Repeater1" runat="server" onitemdatabound="Repeater1_ItemDataBound">
<ItemTemplate>
<div class="user">
Name: <%# DataBinder.Eval(Container, "DataItem.Name")%>
Email: <%# DataBinder.Eval(Container, "DataItem.Email")%>
Active: <%# FormatActive((int)DataBinder.Eval(Container, "DataItem.Active"))%>
Status: <%# FormatStatus((int)DataBinder.Eval(Container, "DataItem.Status"))%>
</div>
</ItemTemplate>
</asp:Repeater>
Then in your code behind:
protected static FormatActive(int active)
{
return "Formated Active String...";
}
protected static FormatStatus(int status)
{
return "Formated StatusString...";
}
<asp:Repeater ID="Repeater1" runat="server" onitemdatabound="Repeater1_ItemDataBound">
<ItemTemplate>
<div class="user">
Active: <asp:label id="lblActive" Text='<%# DataBinder.Eval(Container, "DataItem.Active")%>' runat="server" />
</div>
</ItemTemplate>
</asp:Repeater>
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
//Do modifications here
YourObjectName person = (YourObjectName)e.Item.DataItem;
//you can now ref the object this row is bound to
//example find a dom element
Label lblActive= (Label)e.Item.FindControl("lblActive");
if(person.Active == 2)
{
lblActive.Text = "This is great";
}
}
}
You could do something like:
<%# (int)DataBinder.Eval(Container, "DataItem.Active") == 0 ? "Active" : "Inactive" %>
no need to use the itemdatabound. Just add a method in your itemtemplate to do the conversion with the dataitem.active as parameter. Add a label and do the following:
Text='<%# String.Format("{0}",Conversion(Eval("dataitem.active")))%>'
Conversion is then a method you leave in your code behind or utility class where you do the conversion.

Hide an element in ASP.net based on an if inside a Repeater

I know how to use a simple If statement wrapped in the <%# tags to hide something, but I don't know how to do it in a repeater when I need to access Container.DataItem, as in I need the dataItem currently being 'repeated'
eg
if (CurrentValidationMessage.Link != "")
{
show a hyperlink
}
Markup:
<asp:Repeater ID="repValidationResults" runat="server">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<a href='<%# ((MttImportValidationMessage)Container.DataItem).EditLink %>'> Link to erroneous Milestone </a>
<%# ((MttImportValidationMessage)Container.DataItem).Message %>
<br />
</ItemTemplate>
</asp:Repeater>
It might be more maintainable if you just tagged the controls in the repeater with id's and runat='server' and reference the DataItem in the ItemDataBound event by using e.Item.DataItem.
Then use e.Item.FindControl to reference your controls in the ItemTemplate and perform your logic.
protected void repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
Domain.Employee employee = (Domain.Employee)e.Item.DataItem;
Control myControl = (Control)e.Item.FindControl("controlID");
//Perform logic
}
}
use ItemDataBound Event with repeater, and make the "a" tag with a runat="server" property and ID
protected void repValidationResults_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem item = e.Item;
if (item.ItemType == ListItemType.AlternatingItem || item.ItemType == ListItemType.Item)
{
HyperLink link = (HyperLink) item.FindControl("link");
//Do all your logic here :)
}
}
MarkUp:
<asp:Repeater ID="repValidationResults" runat="server">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<a runat="server" ID="link"> Link to erroneous Milestone </a>
<%# ((MttImportValidationMessage)Container.DataItem).Message %>
<br />
</ItemTemplate>
</asp:Repeater>

Categories

Resources