I am using Asp.net 4.5, C#.
I have a reapter that has some DataSource Bind to it:
<asp:Repeater ItemType="Product" ID="ProductsArea" runat="server">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
...
</ItemTemplate>
<FooterTemplate></FooterTemplate>
</asp:Repeater>
Inside this repeater, I would like a refrence to the current Iterated Item.
I know I can use <%#Item%> and that I can Use <%#Container.DataItem%>. If I want to get to a field, I can use <%#Item.fieldName%> or Eval it.
But I want to make a condition on a field, How can I get the refrence to the #Item in order to do something like this:
<% if (#Item.field>3)%>, <%if (#Container.DataItem.field<4)%>
I would acautley would like to have a refrence like this
<%var item = #Item%> and than to use it whenever I need.
Ofcourse the syntax above is invalid, How to achieve this properley?
I'd use ItemDataBound instead. That makes the code much more readable, maintainable and robust(compile time type safety).
protected void Product_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// presuming the source of the repeater is a DataTable:
DataRowView rv = (DataRowView) e.Item.DataItem;
string field4 = rv.Row.Field<string>(3); // presuming the type of it is string
// ...
}
}
Cast e.Item.DataItem to the actual type. If you need to find a control in the ItemTemplate use e.Item.FindControl and cast it appropriately. Of course you have to add the event-handler:
<asp:Repeater OnItemDataBound="Product_ItemDataBound" ItemType="Product" ID="ProductsArea" runat="server">
Related
I'm getting started with Sitecore and am having a hard time getting images stored in a TreeList to display properly in an aspnet repeater.
In the markup, I have a repeater that is meant to list the images using an sc:Image item.
<asp:Repeater ID="rptLogos" runat="server" OnItemDataBound="rptLogos_ItemDataBound" >
<ItemTemplate>
<a title="Logo" href="#">
<sc:Image runat="server" ID="img" field="image logos" />
</a>
</ItemTemplate>
</asp:Repeater>
In the code behind, I'm retrieving a MultilistField and setting the repeater's data source with the TargetIDs like so
Sitecore.Data.Fields.MultilistField mlLogos = Footer.Fields["Logos"];
if (mlPartnerLogos != null)
{
rptLogos.DataSource = mlLogos.TargetIDs;
rptLogos.DataBind();
}
In the ItemDataBound event I am then converting each ID to an item, grabbing the image control from the repeater and setting the Item field for the Sitecore.Web.UI.WebControls.Image item.
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
ID targetId = e.Item.DataItem as ID;
if (!targetId.IsNull)
{
MediaItem targetItem = Sitecore.Context.Database.GetItem(targetId);
if (targetItem != null)
{
var phImage = e.Item.FindControl("img") as Sitecore.Web.UI.WebControls.Image;
phImage.Item = targetItem;
}
}
}
If I debug the code, it seems to be retrieving the data without any issues. However, in the markup, instead of having the translated to an field, I'm just getting blank text.
The same "idea" of grabbing a Sitecore Item and assigning it to a Sitecore.Web.UI.WebControls.Image item is working fine elsewhere where I have a single item, although I did notice that if I change the sc:Image tag's field to anything other than the name in lowercase of the field name in sitecore it won't work. If this is the issue though, I'm a bit confused as to what the Field name should be for the images within the TreeList though.
I also have a strange feeling that the way I'm retrieving the items and trying to assign them may be a bit too "bloated", and there may be a simpler way of doing it.
Any help would be greatly appreciated. Thank you.
Edit:
Fixed as suggested by replacing the sc:image with an asp:Image and changing the ItemDataBound to
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
ID targetId = e.Item.DataItem as ID;
if (!targetId.IsNull)
{
MediaItem targetItem = Sitecore.Context.Database.GetItem(targetId);
if (targetItem != null)
{
var phImage = e.Item.FindControl("img") as System.Web.UI.WebControls.Image;
phImage.ImageUrl = Sitecore.Resources.Media.MediaManager.GetMediaUrl(targetItem);
}
}
}
The sc:image control is to be used to display fields of an item. I think it's a better approach to just use an asp:image control and fill the image url. If you use the MediaManager you can get the image url from your image item.
Martijn is right. I'd like to add that skipping the OnItemDataBound is better. You should use databinding, much easier. Replace mlLogos.TargetIDs with the items and you are good to go!
So I have tried and searched far and wide but cannot get my nested repeater to work properly.
<asp:Repeater ID="rptrParent" runat="server">
<ItemTemplate>
<dl class="StudentTasksList">
<dt><%# Eval("ClassCode") %></dt>
<asp:Repeater ID="rptrChild" runat="server">
<ItemTemplate>
<dd><%# Eval("Title") %></dd>
</ItemTemplate>
</asp:Repeater>
</dl>
</ItemTemplate>
</asp:Repeater>
C# Code
private void ListTasks()
{
using (StudentContext syndb = new StudentContext())
{
using (TaskContext dbdb = new TaskContext())
{
// Iterate through each active Class for the current Student finding any tasks not archived for this year
var ClassTasks = (from c in syndb.GetClasses()
where c.Students.Select(y => y.StudentID).Contains(LoggedInUserID)
join t in dbdb.Tasks on c.ClassCode equals t.ClassCode
where !t.Archive.HasValue || t.Archive.HasValue && t.Archive.Value && t.DueDate.Value.Year == DateTime.Now.Year
group c by c.ClassCode);
rptrParent.DataSource = ClassTasks;
rptrParent.DataBind();
}
}
}
So ClassCode comes from the GetClasses() method for the selected student, and Title is the name of any Titles found in the Tasks join for the current Class. The Result I need is a list of the classes for a student with any related task titles under each of the ClassCode. I have tried this several different ways so this may not be the best sample of what I am trying to do. I would get great if someone could show me a LINQ C# example of a joined linq query that populates a nested repeater as I cannot find anything decent enough to work this one out.
I would also like to know how to populate an N/A in place if the class doesn't have any tasks, but I wont push my luck.
To populate the inner repeater, you must handle the ItemDataBound event of the parent repeater like this:
<asp:Repeater ID="rptrParent" runat="server" OnItemDataBound="rptrParent_ItemDataBound">
And in the code behind
protected void rptrParent_ItemDataBound(object sender, RepeaterItemEventArgs e) {
RepeaterItem item = e.Item;
if ((item.ItemType == ListItemType.Item) || (item.ItemType == ListItemType.AlternatingItem)) {
Repeater rptrChild = (Repeater)item.FindControl("rptrChild");
rptrChild.DataSource = DataBinder.Eval(item.DataItem, "Group");
rptrChild.DataBind();
}
}
I guess that the property of the data item you need to use as data source of the inner repeater is Group as you are grouping in your LINQ statement, but maybe you need to change that...
As far as I know LINQ dose not play any role in data binding. The LINQ query you have mentioned looks find and may populate data as you needed. But You have nasted Repeater so "rptrParent.DataBind();" will bind the outer most repeater only. I think you have to write ItemDataBound event for "rptrParent" and find child repeater control assign it with group you got from LINQ query.
Hope this will help you.
I can get the selected index of the gridview but i want to get the actual data that is inside the grid. I want to select a row in the grid and be able to access the "Client Id" column's actual data value. The grid is working fine and I am able to access the SelectedIndexChanged event. I have then been trying with no luck to find a way to get the information that is displayed in the grid. Any help would be greatly appreciated.
Again, I need to get access to all data that is displayed in the grid form the codebehind.
This is what data keys are for. Just designate the columns you want to access as data keys, like in the example shown below.
<telerik:RadGrid ID="RadGrid1" runat="server" ...>
<MasterTableView DataKeyNames="Column1, Column2, Column3" ...>
...
</MasterTableView>
</telerik>
Once the data keys have been assigned in the markup, you can access them in code-behind by row, or using the SelectedValues property.
if (RadGrid1.SelectedItems.Count > 0)
{
//access a string value
string column1 = RadGrid1.SelectedValues["Column1"].ToString();
//access an integer value
int column2 = (int)RadGrid1.SelectedValues["Column2"];
}
You could do it like this:
foreach (GridDataItem item in RadGrid1.MasterTableView.Items)
{
if (item.selected == true)
string mydata = item["ColumnName"].Text;
}
I recommend you read the documentation on this site http://www.telerik.com/help/aspnet/grid/grdaccessingcellsandrows.html; it will sure help you a lot with Telerik components.
Use DataKeys as James Johnson suggested. You cannot access DataItem property of the GridDataItem in SelectedIndexChanged event. It will be null. According to Telerik documentation "DataItem object is available only when grid binds to data."
When DateItem is available, as in the ItemCreated event, you could do a cast to your original data type MyType:
private void RadGrid_ItemCreated(object sender, Telerik.Web.UI.GridItemEventArgs e)
{
if ((e.Item is GridDataItem)) {
GridDataItem gridDataItem = (GridDataItem)e.Item;
MyType dataItem = (MyType)gridDataItem.DataItem;
}
}
I am new to Repeater and DataBinding and I need help using it.
In PageLoad, I have
var photos = from p in MyDataContext.Photos
select new {
p,
Url = p.GetImageUrl()
};
repeater1.DataSource = photos;
repeater1.DataBind();
In the Repeater control, I have
<ItemTemplate>
<% Photo p = (Photo) Eval("p"); %> <!-- Apparently I can't do this -->
...
<asp:TextBox runat="server" ID="txtTime" Text='<%= p.Time == null ? "" : ((DateTime)p.Time).ToString("dd/MM/yyyy HH:mm:ss") %>' />
...
</ItemTemplate>
But that is wrong.
What I need is to get the Photo object in ItemTemplate so I can do things with it (eg. to display the time as in the second line in ItemTemplate above). Is it even possible to do this in a Repeater?
Could someone point me to the right direction?
Thank you in advance!
Try something like this In the onDatabound event
if (e.Item.ItemType = ListItemType.Item)
{
photo p = (photo)e.DataItem;
Textbox txtTime = (Textbox)e.Item.FindControl("txtTime");
txtTime.text = (p.Time == null ? "" : ((DateTime)p.Time).ToString("dd/MM/yyyy HH:mm:ss"));
}
Edit -
Sorry, I didn't see the extra Url there. I looks like you might have to create a small class or struct.
See this Stackoverflow link for a hack workaround.
Paul Suart's post in that thread made a valid point.
Have you tried just:
<%# Eval("p") %>
instead of
<% Photo p = (Photo) Eval("p"); %>
I use an alternative method. In my "Register" I import the object class:
<%# Import Namespace="Test.Test.TO" %>
With this It's possible use your object...
Next, I created an object the same type I want to bound in my codebehind, global variable...
public Test test;
In my Repeater inside ItemTemplete:
<span style="display: none;"> <%# test = (Test)Container.DataItem %> </span>
Now, you can use all object's properties, inclusive ToString to format with culture...
Sorry for my english.
ASPX : Code
<asp:repeater id="repeater" runat="server">
<headerTemplate></headerTemplate>
<itemtemplate></itemtemplate>
<footerTemplate> <asp:literal id=findme runate=server> </footerTeplate>
</asp:repeater>
What i am looking for is source code to be able to find the control within the footer of a data repeater. Im familiar with the basic "FindControl" when i do a databind or look for control within the page itself, but how can i find the control within a footer template of a data repeater?
Is this even possible? and if so how can i please get some assistance,
thanks again to all!!!
[update]
i need to be able to do this after the databind
Protected Sub Repeater1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
If e.Item.ItemType = ListItemType.Footer Then
Dim Lit As Literal = CType(e.Item.FindControl("findme"), Literal)
End If
End Sub
There are a number of ways that you can do it, the exact way depends on when you want to get access to the control.
If you want it during DataBind, simply do the following inside the item Databound.
if(e.Item.ItemType == ItemType.Footer)
{
Literal findMe = (Literal)e.Item.FindControl("findMe");
//Your code here
}
If you want to find it at another point in time, access the repeater's Item collection, then find the "Footer" item, and from that item, you can find the control.
Update
Based on your added note, you can do this by enumerating the item collection, below is an example with a repeater that has an id of myRepeater.
foreach (RepeaterItem item in myRepeater.Items)
{
if (item.ItemType == ListItemType.Footer)
{
Literal findMe = (Literal)item.FindControl("findMe");
//Do your stuff
}
}
I think you have to check the ListItemType in an ItemDataBound event handler. You can check for Header or Footer and then use the FindControl method to access the control.
Foreach (RepeaterItem item in myRepeater.Controls)
This will work better as Items collection doesn't contain header and footer
If you need to get the Footer after DataBind (which is what the OP appears to want) then you can use the following:
RepeaterItem item= (RepeaterItem)myRepeater.Controls[myRepeater.Controls.Count - 1];
if (item.ItemType == ListItemType.Footer) {
Literal findMe = (Literal)item.FindControl("findMe");
}