Custom user control with repeating data - c#

Below is code that I'm aiming for. I need a custom user control that can be data bound to, but also contain other content (so just a raw repeater wont suffice). The end goal is something along the lines of:
<MyControls:Control1 runat="server" id="Control1">
<headertemplate>
<tr>
<td>ID</td>
<td>Username</td>
</tr>
</headertemplate>
<itemtemplate>
<tr>
<td><%#((User)Container.DataItem).ID %></td>
<td><%#((User)Container.DataItem).Username %></td>
</tr>
</itemtemplate>
</MyControls>
And:
var users = GetUsersList();
Control1.DataSource = users;
Control1.DataBind();
And looks like this:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl1.ascx.cs" Inherits="Controls.MyControl1" %>
<asp:PlaceHolder runat="server" ID="Wrapper">
<h2>Results</h2>
<table>
<%=HeaderTemplate%>
<%
if(ItemTemplate.AnyItems()){
foreach(var item in ItemTemplate){
}
}
else
{
%>Nothing here<%
}
%>
</table>
<MyControls:AnotherControl runat="server" />
</asp:PlaceHolder>
I've found a page on ScottGu's Blog that appears to show what I want:
https://weblogs.asp.net/scottgu/Supporting-Templates-with-ASP.NET-User-Controls
But the linked to tutorial 404's now! All other examples I've found don't seem to be well written and very hard to pick apart.
Any help on how to achieve the above would be much appreciated.

It looks like you are getting 2 different Controls mixed up. UserControl and Repeater (I think).
To bind data in to a Control inside a UserControl, you need to make that Control accessible from the parent. You can do this by creating a public property inside the UserControl.
public Repeater myRepeater
{
get
{
return Repeater1;
}
set
{
Repeater1 = value;
}
}
UserControl ascx with the Repeater Control
<table border="1">
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<tr>
<td>ID</td>
<td>Username</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("ID") %></td>
<td><%# Eval("Username") %></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
Now you have access to Repeater1 in the parent due to the public property.
Control1.myRepeater.DataSource = users;
Control1.myRepeater.DataBind();
And leave the control on the aspx parent empty.
<MyControls:Control1 runat="server" id="Control1"></MyControls>

Related

How can I create a table with dynamic columns using asp.net controls?

Background: My data model is a List<PersonDetail>, where PersonDetail contains properties like FirstName, LastName, etc, and the List can be any size.
I want to create a table that can compare these PersonDetails side-by-side. This means for each column I need to take the data in a single PersonDetail and spread it across my 8 rows. Then do the same for the next PersonDetail.
I have a constraint where I can only use an Asp.Net control (ListView, GridView, Repeater, etc.) along with control.DataSource and control.DataBind() to create my table.
The template I want to do is something like:
<LayoutTemplate>
<table>
<tr>
<asp:PlaceHolder runat="server" ID="itemPlaceHolder1"></asp:PlaceHolder>
</tr>
<tr>
<asp:PlaceHolder runat="server" ID="itemPlaceHolder2"></asp:PlaceHolder>
</tr>
<!-- and so on -->
</table>
</LayoutTemplate>
<ItemTemplate1>
<td>
<asp:Label ID="LabelFirstName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "FirstName")%>'></asp:Label>
</td>
</ItemTemplate1>
<ItemTemplate2>
<td>
<asp:Label ID="LabelLastName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "LastName")%>'></asp:Label>
</td>
</ItemTemplate2>
<!-- and so on -->
Where the above ItemTemplates would be the only parts that repeat in the table.
I've tried all three control options and it doesn't seem to be supported without complicating the code-behind.
Is there a better data model I could use that can interface with another control? I've seen solutions like DataTable, but not sure if that will solve my problem..
Any ideas?
<table border="1">
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<tr>
<td><%# DataBinder.Eval(Container.DataItem, "FirstName") %></td>
<td><%# DataBinder.Eval(Container.DataItem, "LastName") %></td>
</tr>
<tr>
<td><%# DataBinder.Eval(Container.DataItem, "Street") %></td>
<td><%# DataBinder.Eval(Container.DataItem, "City") %></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>

How can i access data from parent repeater in nested repeater?

I Use modelbinding to pass a list of Post Objects containing post id,Title.. to my page.aspx
Each Post Objects also contains a list of Comment Objects and these are
the ones i want to access in the inner repeater.
Here the code from my page.aspx
<asp:Repeater runat="server" ID="repeater1" ItemType="OOPBLOG.Model.Classes.Post"
SelectMethod="LoadPosts"
OnCallingDataMethods="postView">
<ItemTemplate >
<table>
<tr>
<td><%#Item.Title %></td>
</tr>
<tr>
<td><%#Item.Body %></td>
</tr>
<tr>
<td><%#Item.Date %></td>
</tr>
<asp:Repeater runat="server" ID="repeater2">
<ItemTemplate>
<table>
<tr>
<td>
<%# ((RepeaterItem)Container.Parent.Parent).ItemType %>
</td>
</tr>
</table>
</ItemTemplate>
</asp:Repeater>
</table>
</ItemTemplate>
</asp:Repeater>
To conclude, what i want, is to access the Item.Comments List in the nested repeater. How can i do this?

LinkButton in Repeater causes postback and button doesn't

Ok so I have an update panel sorrounding my controls. I have 2 dropdownlists which have functions they run from codebehind and a repeater of items. I've done the test in a Repeater using a button it doesn't do a postback, but the linkbutton does. What am I doing wrong?
also this is inside a usercontrol no aspx page.
<asp:UpdatePanel ID="upLocation" runat="server" UpdateMode="Conditional" RenderMode="Inline">
<ContentTemplate>
<asp:Repeater ID="rptMuniProducts" runat="server">
<HeaderTemplate>
<table class="table">
<thead>
<tr>
<th class="w80"></th>
<th>Product</th>
<th>Product Type</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td class="actions">
<asp:Button ID="btnProd" runat="server" OnClick="btnProd_Click" Text="test" />
<asp:LinkButton ID="lnkDeleteProd" runat="server" OnClick="lnkDeleteProd_Click">Link Test</asp:LinkButton>
<asp:HiddenField ID="hdnId" runat="server" Value='<%# DataBinder.Eval(Container, "DataItem.Id") %>' />
</td>
<td><%# DataBinder.Eval(Container, "DataItem.Name") %></td>
<td><%# DataBinder.Eval(Container, "DataItem.Producttype") %></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
Have you tried setting ClientIDMode=Auto on the LinkButton? There's a long-standing .NET bug with doPostBack and non-auto client ids.

Repeater inside a repeater with jQuery accordion

I recently did a nested repeater according to this tutorial. The same thing
http://www.codeproject.com/Articles/6140/A-quick-guide-to-using-nested-repeaters-in-ASP-NET
But I added a jQuery accordion just like this example:
http://www.snyderplace.com/demos/accordion.html
Everything is good, but I realized some UI issues. I mean for example if one of my nested repeaters has 100 records and another has just 1 record, for this second with just 1 record, it has a blank space reserved as it had 100 records also. Someone knows how to fit the height each nested repeater to its elements?
<div id="accordion">
<asp:Repeater ID="summary" runat="server" OnItemDataBound="summary_ItemDataBound">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<div>
Id:<asp:Literal ID="litCategory" runat="server" />
</div>
<div>
<asp:Repeater ID="detail" runat="server" OnItemDataBound="detail_ItemDataBound">
<HeaderTemplate>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><asp:Literal ID="litID" runat="server" /></td>
<td><asp:Literal ID="litName" runat="server" /></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:Repeater>
</div>
</ItemTemplate>
<FooterTemplate>
</FooterTemplate>
</asp:Repeater>
</div>
I got it! I found this solution!
$(function () {
$("#accordion").accordion({
collapsible: true,
heightStyle: "content"
});
});
I need to specify that to attributes and that's it!

Asp.net Ajax problem

I installed the Asp.net Ajax toolkit. In my site I use the NummericUpDown from that toolkit.
Now, I want that a label changes when the NummericUpDown Textboxes changes. I try to use JavaScript for this, but I always get the following error:
'ASP.orders_aspx' does not contain a definition for 'changeAmount' and no extension method 'changeAmount' accepting a first argument of type 'ASP.orders_aspx' could be found (are you missing a using directive or an assembly reference?)
This is my code:
<%# Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeFile="orders.aspx.cs" Inherits="orders" Title="the BookStore" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">
<script type="text/javascript">
function changeAmount()
{
var amount = document.getElementById("txtCount");
var total = 10 * amount.value;
document.getElementById("lblPrice").value = total;
}
</script>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<ajaxToolkit:ToolkitScriptManager runat="Server" EnablePartialRendering="true" ID="ScriptManager1" />
<h1 id="H1" runat="server">
Bestellen</h1>
<asp:Panel ID="pnlZoeken" runat="server" Visible="true">
<asp:ObjectDataSource ID="objdsSelectedBooks" runat="server" OnSelecting="objdsSelectedBooks_Selecting"
TypeName="DAL.BooksDAL"></asp:ObjectDataSource>
<h3>
Overzicht van het gekozen boek</h3>
<asp:FormView ID="fvBestelBoek" runat="server" Width="650">
<ItemTemplate>
<h3>
Aantal boeken bestellen</h3>
<table width="650">
<tr class="txtBox">
<td>
Boek
</td>
<td>
Prijs
</td>
<td>
Aantal
</td>
<td>
Korting
</td>
<td>
Totale Prijs
</td>
</tr>
<tr>
<td>
<%# Eval("TITLE") %>
</td>
<td>
<asp:Label ID="lblPrice" runat="server" Text='<%# Eval("PRICE") %>' />
</td>
<td>
<asp:TextBox OnTextChanged="changeAmount()" ID="txtCount" runat="server"></asp:TextBox>
<ajaxToolkit:NumericUpDownExtender ID="NumericUpDownExtender1" runat="server" TargetControlID="txtCount"
Width="50" Minimum="1" ServiceDownMethod="" ServiceUpMethod="" />
</td>
<td>
-
</td>
<td>
<asp:Label ID="lblAmount" runat="server" />
</td>
</tr>
</table>
</ItemTemplate>
</asp:FormView>
<asp:Button ID="btnBestel" runat="server" CssClass="btn" Text="Bestel" OnClick="btnBestel_Click1" />
<asp:Button ID="btnReChoose" runat="server" CssClass="btnDelete" Text="Kies een ander boek"
OnClick="btnRechoose_Click" />
</asp:Panel>
</asp:Content>
Does anyone know the answer?
Thanks a lot, Vincent
You're trying to assign a client-side method to the OnTextChanged event, which is a server-side event.
Also, your javascript is referencing the server id of the label and textbox. The WinForms engine appends characters to this depending where the control is nested. Use <%=myControl.ClientID%> to get around this.
You need to use some pure Javascript for this:
window.onload=function(){
//assign client method to textbox
document.getElementById('<%=txtCount.ClientID%>').onChange = function(){
var amount = document.getElementById('<%=txtCount.ClientID%>');
var total = 10 * amount.value;
document.getElementById('<%=lblPrice.ClientID%>').value = total;
}
}
Place that on your page instead of your current Javascript and get rid of the OnTextChanged="changeAmount()" attribute.
You set OnTextChanged for TextBox. It is refer to server method, that is fired on PostBack.
If you want to handle Up and Down events in background by method on your Page, you have to set
properties ServiceUpPath and ServiceUpMethod for NumericUpDown tag.
If you want to handle client events - set custom Up and Down buttons and set property OnClientClick to them.
See
http://www.asp.net/AJAX/AjaxControlToolkit/Samples/NumericUpDown/NumericUpDown.aspx

Categories