I have a problem with the repeater asp control.
I have a table on my database called course with columns CourseID, CourseName, CourseLink and another table called module with columns ModuleID, ModuleName. And another table called timetable with columns CourseID and ModuleID.
The way this works is when I click on HyperLink1,the paragraph bellow with the the same course id, it would changes the paragraph's style display from hidden to show (I used JavaScript to complete this function so it's not the problem here).
What I would like to know is, how can I list the ModuleNames That relate to that specif course ID.
I was thinking of using another repeater inside a repeater. However that just complicate things and to be hones really confuses me.
How can I get this to work, don't work about the sql because I am comfortable in creating a select command.
Here is the the ASP.NET forum.
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="DataSource1">
<ItemTemplate>
<p>
<a id="HyperLink1" runat="server" href='<%# Eval("courselink") %>'>
<%# Eval("CourseName") %>
</a> <br />
</p>
<p id='<%# Eval("CourseID") %>' style="display:none">
<%# Eval("ModulName") %>
</p>
<br />
</ItemTemplate>
</asp:Repeater>
Thank you for your time and I look forward to finding out what I can do to solve this problem.
You pretty much will need to use another repeater, the trick (if I remember correctly has I haven't used the legacy ASP.NET Web Forms since 2011) is that you hook into the ItemDataBound event in your code behind for the parent repeater and then use the Event Arguments to get the id that you associate to your child table, get that data, lookup the repeater by id from Repeater (I think it's the sender but there is some way to get at it) and bind the data.
I want to note this is much easier and cleaner with ASP.NET MVC and the use of ASP.NET Web Forms is generally discouraged.
It could be the worst this way
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="DataSource1">
<ItemTemplate>
<p>
<a id="HyperLink1" runat="server" href='<%# Eval("courselink") %>'>
<%# Eval("CourseName") %>
</a> <br />
</p>
<p id='<%# Eval("CourseID") %>' style="display:none">
<%# moduleName(Eval("id").ToString()) %>
</p>
<br />
</ItemTemplate>
public string moduleName(string id)
{
string returnValue = "<ul>";
using (SqlConnection con = new SqlConnection(DB))
{
using (SqlCommand com = new SqlCommand("SELECT * FROM module WHERE id = #id", con))
{
com.Parameters.AddWithValue("#id", id);
if (con.State == System.Data.ConnectionState.Closed)
{
con.Open();
using (SqlDataReader dr = com.ExecuteReader())
{
while (dr.Read())
{
returnValue += "<li>"+ dr["modulename"].ToString()+"</li>";
}
}
con.Close();
}
}
}
returnValue += "</ul>";
return returnValue;
}
The best solution would be to create a strongly typed model for your presentation and don't use Eval, you would get something like this in your webform:
<asp:Repeater runat="server" DataSourceID="<%# Model %>">
<ItemTemplate>
<p>
<%# ((Course)Container.DataItem).Name %>
</p>
<p id='<%# ((Course)Container.DataItem).ID %>' style="display:none">
<asp:Repeater runat="server" DataSource="<%# ((Course)Container.DataItem).Modules %>">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><%# ((Module)Container.DataItem).Name %></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</p>
</ItemTemplate>
Then in your code behind create the following property:
public List<Course> Model
{
get
{
List<Course> courses = new List<Course>();
// Some example data, in your situation you should instantiate the classes based on the data from the database.
Course exampleCourse = new Course();
exampleCourse.ID = 1;
exampleCourse.Name = "Example course";
// Create example module 1
Module exampleModule1 = new Module();
exampleModule1.ID = 10;
exampleModule1.Name = "Example Module 1";
// Create example module 2
Module exampleModule2 = new Module();
exampleModule2.ID = 11;
exampleModule2.Name = "Example Module 2";
// add modules to the course
exampleCourse.Modules.Add(exampleModule1);
exampleCourse.Modules.Add(exampleModule2);
// add course to the courses
courses.Add(exampleCourse);
return courses;
}
}
Classes needed:
public class Course
{
public int ID { get; set; }
public string Link { get; set; }
public string Name { get; set; }
public List<Module> Modules { get; set; }
public Course()
{
this.Modules = new List<Module>();
}
}
public class Module
{
public int ID { get; set; }
public string Name { get; set; }
}
Last, in your page load, don't forget to databind:
protected void Page_Load(object sender, EventArgs e)
{
this.DataBind();
}
Related
I want to transfer the text of a hyperlink through a session inside a repeater. But I can not think of the logic to do this. My repeater generates links within that dropdown menu and I want to get the text that appears in the link and pass it to another page Sectors.aspx. This is what I have done so far:
--- edit ---
I want that when the link is clicked, the text that is in the link is passed to the other page. For example, the menu has two links, APPLE and BANANA. When the user clicks APPLE, I want the next page Sectors.aspx to know that the user clicked APPLE and not the other options.
ASPX Page:
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<div class="dropdown">
<button class="dropbtn">Setor</button>
<div class="dropdown_content">
<asp:Repeater ID="sectors_menu" runat="server">
<ItemTemplate>
<asp:HyperLink id="hyperlink1" NavigateUrl="Sectors.aspx" Text='<%#((System.Data.DataRowView)Container.DataItem)["sector"] %>' runat="server"></asp:HyperLink>
</ItemTemplate>
</asp:Repeater>
</div>
</div>
</asp:Content>
Code Behind
public partial class _Default : System.Web.UI.Page
{
MySqlConnection mysql_connection = new MySqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
string mysql_string;
MySqlDataAdapter mysql_data_adapter;
public void Page_Load(object sender, EventArgs e)
{
Sector_label();
}
public void Sector_label()
{
mysql_string = "SELECT * FROM employees GROUP BY sector";
mysql_data_adapter = new MySqlDataAdapter(mysql_string, mysql_connection);
DataTable data_table = new DataTable();
mysql_data_adapter.Fill(data_table);
DataView data_view = new DataView(data_table);
sectors_menu.DataSource = data_view;
sectors_menu.DataBind();
for (int count = 0; count < sectors_menu.Items.Count; count++)
{
var test = (HyperLink)sectors_menu.Items[count].FindControl("hyperlink1");
Session["session_hyperlink"] = test.Text;
// Debug.WriteLine(test.Text);
}
}
}
You could add the text as a parameter of the NavigateUrl:
<ItemTemplate>
<asp:HyperLink id="hyperlink1" NavigateUrl='<%# "Sectors.aspx?sector=" + Server.UrlEncode(((System.Data.DataRowView)Container.DataItem)["sector"]).ToString() %>' Text='<%#((System.Data.DataRowView)Container.DataItem)["sector"] %>' runat="server"></asp:HyperLink>
</ItemTemplate>
Then, Sectors.aspx can retrieve it through the "sector" parameter:
protected void Page_Load(object sender, EventArgs e)
{
string sector = Request.Params["sector"];
}
That id="hyperlink1" parameter looks fishy, though. You don't want all your hyperlinks to have the same ID.
Just replace hyperlink tag with this code ,
<asp:HyperLink runat="server" Navigateurl='<%#"Sectors.aspx?mySector="+ Eval("sector") %>'
Text='<%#((System.Data.DataRowView)Container.DataItem)["sector"] %>' />
===================
UPDATE: 29/06/2017
I am trying to get the delete button within my repeater control to function as intended. The aim is to get the button to "fire" the stored procedure within my MSSQL database.
I would like to thank Win for his in-depth response although I am still struggling to resolve the issue. I accept that I was perhaps unable to articulate my question correctly in the first instance. I have therefore edited my post to show the code I have now. I am confident that I am close to cracking the issue and would sincerely appreciate any assistance.
Code within my *.*aspx page:
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$
ConnectionStrings:ConnectionString %>" SelectCommand="SELECT * FROM
[Comments] WHERE ([Ad_ID] = #Ad_ID) ORDER BY [CommentCreationDateTime] ASC">
And further down the *.*aspx page:
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource2"
Visible="True" OnItemCommand="Repeater1_ItemCommand">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<table id="displayCommentsTable" class="displayCommentsTable">
<tr class="displayCommentsTable"><td class="displayCommentsTable">
<asp:ImageButton ID="deleteCommentImageButtonReal" runat="server"
class="rightCross" ImageUrl="images/Red-Cross-Mark-PNG.png"
OnClientClick="return confirm('Are you sure you wish to delete this
comment?');" Height="11" Width="11" CommandName="Delete"
CommandArgument='<%# Eval("Comment_ID") %>' /><%# Eval("CommenterName") %>
commented on <%# Eval("CommentCreationDateTime", "{0:d/M/yyyy <i> hh:mm:ss
tt}") %>
</td></tr>
<tr class="displayCommentsTable"><td class="displayCommentsTable"><%#
Eval("CommentText") %><br /></td></tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
And finally, my code behind where the magic should be happening but isn't:
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
DeleteCommentById(Convert.ToInt32(e.CommandArgument))
}
}
private void DeleteCommentById(int Comment_ID)
{
SqlConnection conn;
SqlCommand deleteCommentById;
string connectionString =
ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
conn = new SqlConnection(connectionString);
deleteCommentById = new SqlCommand("usp_deleteCommentById", conn);
deleteCommentById.CommandType = System.Data.CommandType.StoredProcedure;
deleteCommentById.Parameters.Add("#Comment_ID", System.Data.SqlDbType.Int);
deleteCommentById.Parameters["#Comment_ID"].Value = Comment_ID;
conn.Open();
deleteCommentById.ExecuteNonQuery();
conn.Close();
}
It is perhaps worth mentioning that if I "hard code" the line I am attempting to delete then it works. For example, if I used the following within my delete button:
CommandArgument='44'
then the stored procedure would fire and affect line 44 as intended.
Easiest way is to use ItemCommand event.
<%# Page Language="C#" AutoEventWireup="true"
CodeBehind="RepeaterDemo.aspx.cs" Inherits="DemoWebForm.RepeaterDemo" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:Repeater ID="Repeater1" OnItemCommand="Repeater1_ItemCommand" runat="server">
<ItemTemplate>
<p>
<%#Eval("Name") %>
<asp:ImageButton CommandArgument='<%# Eval("Id") %>' runat="server"
ImageUrl="~/Images/Delete.png" CommandName="Delete" />
</p>
</ItemTemplate>
</asp:Repeater>
</form>
</body>
</html>
Code Behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DemoWebForm
{
public partial class RepeaterDemo : System.Web.UI.Page
{
public class Comment
{
public int Id { get; set; }
public string Name { get; set; }
}
public static IList<Comment> Comments = new List<Comment>
{
new Comment {Id = 1, Name = "One"},
new Comment {Id = 2, Name = "Two"},
new Comment {Id = 3, Name = "Three"}
};
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Repeater1.DataSource = Comments;
Repeater1.DataBind();
}
}
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
int id = Convert.ToInt32(e.CommandArgument);
var comment = Comments.FirstOrDefault(c => c.Id == id);
Comments.Remove(comment);
Repeater1.DataSource = Comments;
Repeater1.DataBind();
}
}
}
}
In what event are you trying to access the repeater button?
You will need to try to find the control inside the repeater item.
For eg:
Button btn1 = (Button)rptItem.FindControl("btn1");
Everything was working fine but as I had not specified to only return results that had not been soft deleted, everything was getting returned. Noob mistake, learnt something for the future!
I am attempting to list a group of Associations, within each association is a 'widget' that is assigned to the association. The list will include the Association name and any widget assigned to it. The catch is that the inner widget list needs to be sorted by DisplaySequence.
EDMX Model Below:
Simplified Repeater Mark-Up
<asp:Repeater ID="rptAssociations" runat="server">
<ItemTemplate>
<div data-type="assn" id="<%# ((Association)Container.DataItem).AssociationID %>">
<h3 style="margin-top:15px;"><%# ((Association)Container.DataItem).Acronym %> - <%# ((Association)Container.DataItem).Name %></h3>
<asp:Repeater runat="server" ID="rptWidgets" DataSource="<%# ((Association)Container.DataItem).AssociationWidgets %>" >
<HeaderTemplate>
<ul class="WidgetList">
</HeaderTemplate>
<ItemTemplate>
<li id="<%# ((AssociationWidget)Container.DataItem).DisplaySequence %>"><%# ((AssociationWidget)Container.DataItem).Widget.Name %></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</div>
</ItemTemplate>
</asp:Repeater>
Current Query
var associations = (from a in
context.Associations.Include("AssociationWidgets")
.Include("AssociationWidgets.Widget")
orderby a.Acronym
select a).ToList();
rptAssociations.DataSource = associations;
rptAssociations.DataBind();
I am currently able to get the data that I'm looking for with the setup that I have now. I am looking for the most efficient approach to getting this same data, however, having the Widgets listed in the correct display order.
Is there a different approach to the linq query I should take?
I would approach this like this (untested):
var associations =
context.Associations.Select( a =>
new {
//... specific properties you need
AssociationId = a.AssociationId,
Name = a.Name,
... etc
Widgets = a.AssociateWidgets.OrderBy(aw => aw.DisplaySequence)
.Select(aw => aw.Widget)
}
);
Here you'll get a collection of anonymous types. You can use a concrete type such as
public class AssociationInfo
{
public string Name {get;set;}
...
public IEnumerable<Widget> Widgets{ get;set; }
}
if necessary by replacing 'new {' with 'new AssociationInfo {'
I have the next structure for a menu item:
class MenuItem
{
public string Path, Title;
}
I want to be able to Iterate an object of MenuItem[], creating a new object of asp:HyperLink on each iteration, and to add it to a <ul> list.
One thing that must happen is that each HyperLink will be inside a <li> tag.
How can I do that?
You can use a repeater. In the aspx:
<asp:Repeater ID="repMenuItems" runat="server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><asp:HyperLink ID="lnkMenuItem" runat="server" Text='<%# Eval("Title") %>' NavigateUrl='<%# Eval("Path")%>'/></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
And in the codebehind:
repMenuItems.DataSource = arrMenuItem; // your MenuItem array
repMenuItems.DataBind();
Additionaly you should change your class code for using Public Properties instead of Public Members, like this:
public class MenuItem
{
public string Title {get;set;}
public string Path {get;set;}
}
I recommend you to read more about Properties in .NET, a nice feature for object encapsulation http://msdn.microsoft.com/en-us/library/65zdfbdt(v=vs.71).aspx
Hope this helps you
Need a hand trying to get my rotating banner working properly on my website. I'm using the jquery cycle plugin which manages the rotation. Within my CMS I've got something called a smartform, which contains upto 6 pictures. The code below (something which I wrote by following a tutorial for the banner) works really well. However I would like to somehow get the index of the image and place it within the alt tags. What I am trying to achieve is the alt tag to say "Banner_(ImageIndexNumber)".
Hopefully someone can help, thanks all
C# Codebehind
private void BannerFill(int contentId)
{
try
{
uxBannerContentBlock.DefaultContentID = contentId;
uxBannerContentBlock.Fill();
string xml = uxBannerContentBlock.EkItem.Html;
SmartForm.RotatingBanner.BannerImage bannerGroup = (SmartForm.RotatingBanner.BannerImage)
Ektron.Cms.EkXml.Deserialize(typeof(SmartForm.RotatingBanner.BannerImage), xml);
List<BannerSlide> slides = GetBannerSlides(bannerGroup.Slides);
//Databind//
uxBannerRepeater.DataSource = slides;
uxBannerRepeater.DataBind();
}
catch { }
}
protected List<BannerSlide>
GetBannerSlides(SmartForm.RotatingBanner.BannerImageSlides[] bannerGroupSlides)
{
List<BannerSlide> bSlides = new List<BannerSlide>();
foreach (SmartForm.RotatingBanner.BannerImageSlides bgSlide in bannerGroupSlides)
{
bSlides.Add(new BannerSlide(bgSlide.Image.img.src));
}
return bSlides;
}
public class BannerSlide
{
//properties//
public string SlideImage { get; set; }
//constructor//
public BannerSlide(string slideImage)
{
SlideImage = slideImage;
}
}
Front end
<div class="slideshow">
<CMS:ContentBlock ID="uxBannerContentBlock" runat="server" Visible="false" />
<asp:Repeater runat="server" ID="uxBannerRepeater">
<ItemTemplate>
<img src="<%# DataBinder.Eval( Container.DataItem,"SlideImage") %>" alt="Banner_<%# Container.ItemIndex %>" />
</ItemTemplate>
</asp:Repeater>
alt='<%# "Banner_" + Container.ItemIndex %>'