where does the repeater get it data bound items? - c#

I am having a look at databinding for the first time. I understand that the databound elements are put in the aspx file between <%# and %>. I also understand that a Repeater class is used. Like so:
<asp:Repeater ID="gvEvents" runat="server">
<ItemTemplate>
<div class="eventLogItem">
<h1><%# Eval("Event")%></h1>
<time><%# Eval("Timestamp")%></time><small><%# Eval("User")%></small>
<span class="nav">mouseover to view comments</span>
<textarea disabled="disabled"><%# Eval("Comments") %></textarea>
</div>
</ItemTemplate>
<SeparatorTemplate>
<hr />
</SeparatorTemplate>
</asp:Repeater> `
But where would the aspx code get "Event", "Timestamp" and "User" and "Comments"? There does not seem to be something clear in the code-behind file. What am I missing?

In your code behind you would set the DataSource property of the repeater to some collection of object in which each of those objects contains a property named Event, Timestamp, User, and Comments. If you don't assign a data source, then there won't be anything for the repeater to display. If any of the bound items is missing one of those properties, you'll get an error at runtime.

Look in the code behind for gvEvents.DataSource = ... that is how the database is called for the databinding of the repeater class

Related

Access to div from codebehind who's outside a repeater Asp.net C#

I know its maybe unusual, but i want add htmlGenericControl to a div (it's outside a repeater) in ItemDataBound from CodeBehind..
HtmlGenericControl slider = (HtmlGenericControl)e.Item.FindControl("slider");
htmlGenericControl input = new HtmlGenericControl("input");
input.Attributes.Add("type", "radio");
input.Attributes.Add("name", "slide_switch");
input.Attributes.Add("id", string.Format("projectImage-{0}", item.ProjectImageId));
slider.Controls.Add(input);
but its return null everytime. this is the aspx code:
<div class="slider">
<asp:Repeater ID="rptProjectImages" runat="server" OnItemDataBound="rptProjectImages_ItemDataBound">
<ItemTemplate>
</ItemTemplate>
</asp:Repeater>
</div>
Didnt work with asp.net too long, but probably this should help
<div id="myDiv" runat="server">...</div>
and in codebehind myDiv should be accessible.
Several issues with this code.
First, your div is client-side only, from server-side point of view it's just a string. Turn it into server-side control with:
<div class="slider" runat="server" ID="slider">
Second, FindControl looks for immediate children only, in your case children of the repeater item. slider is not one of those. Moreover, it is not a part of the repeater item template and should be accessible as in in code behind, so just
slider.Controls.Add(...
That is unless slider and the repeater you showed are a part of some other template of some "outer" control. In which case make sure to use that "outer" control to call FindControl on.
Finally, don't mess with id. I bet this is either going to be overridden by ASP.NET, or will cause issues on the page. Instead set client ID mode to static and assign ID property:
input.ClientIDMode = ClientIDMode.Static;
input.ID = string.Format("projectImage_{0}", item.ProjectImageId);
This is eventually output the same value for id you needed, but in more ASP.NET compliant way. One note though is that I replaced "-" with "_" - server side controls cannot have hyphens in ID
FindControl finds a control within another, but does so looking for the control's id. Your "slider" control has no id, it uses a class named "slider" but has no id.
You will need to define the control as
<div runat="server" id="Slider" class="slider">
<asp:Repeater ID="rptProjectImages" runat="server" OnItemDataBound="rptProjectImages_ItemDataBound">
<ItemTemplate>
</ItemTemplate>
</asp:Repeater>
</div>
The runat="server" tells the framework to instantiate that control in your code behind. The id will be the name of the object that is that control. Then in your code, you can do
htmlGenericControl input = new HtmlGenericControl("input");
input.Attributes.Add("type", "radio");
input.Attributes.Add("name", "slide_switch");
input.ID = string.Format("projectImage-{0}", item.ProjectImageId);
Slider.Controls.Add(input);

Cant change text/value of textbox inside repeater

Hello and thanks for taking your time to help me.
I'm trying to change the text of a textbox thats located inside my repeater.
<asp:Repeater runat="server" ID="rpCategories">
<HeaderTemplate>
<ul id="nav_down" class="nav_down">
</HeaderTemplate>
<ItemTemplate>
<li><%# Eval("Title") %></li>
</ItemTemplate>
<FooterTemplate>
<li></li>
<li>Contact</li>
<li><a id="cart_logo"></a>
<asp:Panel runat="server" ID="pnlBasket">
<asp:textbox runat="server" id="txtTotalCount" Enabled="false" CssClass="ltTotalCount"></asp:textbox>
</asp:Panel>
</li>
</ul>
</FooterTemplate>
</asp:Repeater>
It's the asp:textbox with the id="txtTotalCount" that I want to change the text of.
Here is my C# code:
TextBox ltTotalCount = (TextBox)FindControl("lblTotalCount");
ltTotalCount.Text = "1";
But if I run the code I get this error : Object reference not set to an instance of an object.
Would be so happy if someone could tell me what I'm doing wrong.
Becuase lblTotalCount is inside a parent control - the repeater, you have to reference it through the repeater.
You should be able to just add the id of your repeater before FindControl, like this...
TextBox ltTotalCount = (TextBox)rpCategories.FindControl("lblTotalCount");
You have to specify the repeater as the parent control to look for the text box and also since it's repeater its quite possible to have more than one text box with that Id so you have to specify which repeater item to look into like so:
TextBox ltTotalCount = rpCategories.Items[0].FindControl("txtTotalCount") as TextBox;
This will return the textbox in the first row of the repeater.
And you should use the Id value not the CssClass value
The ID is probably being 'enhanced' to prevent duplicate IDs in the rendered HTML. You can verify this by looking at the html.
You can add this to the textbox: ClientIDMode="Static" to make the ID stay the same.
You are getting the error because FindControl is returning a null but you are trying to access it anyway.
[Edit] Someone pointed out that this shouldn't work. I agree, here is what does work:
Control FooterTemplate = rpCategories.Controls[rpCategories.Controls.Count - 1].Controls[0];
TextBox MyTextBox = FooterTemplate.FindControl("txtTotalCount") as TextBox;

How to add class in c#(server) to ListView li item

I'm using Linq in server I fill my list like this
selected MenuId=3;
ul_HeaderMenu.DataSource = data.TABLE_MENUS.ToList();
ul_HeaderMenu.DataBind();
this client code
<asp:ListView ID="ul_HeaderMenu" runat="server" ClientIDMode="Static">
<ItemTemplate >
<li class="li-HeaderMenu" runat="server" ><%# Eval("Name") %>
<div class="TopMenuActive"></div>
</li>
<ItemTemplate>
</asp:ListView>
I need to add class to the li the I building in server some think like this
selected MeduId=3;
ul_HeaderMenu.DataSource = data.TABLE_MENUS.ToList();
ul_HeaderMenu.DataBind();
ul_HeaderMenu.ElementAt[3]AddClass('test');
I just find the way to add class to li.
You could use the itemdatabound event on your list
<asp:ListView OnItemDataBound="YourListView_ItemDataBound" ID="ul_HeaderMenu" runat="server" ClientIDMode="Static">
<ItemTemplate >
<li ID="listItem" class="li-HeaderMenu" runat="server" ><%# Eval("Name") %>
<div class="TopMenuActive"></div>
</li>
<ItemTemplate>
</asp:ListView>
then in code behind, something like this;
protected void YourListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
HtmlGenericControl myLi = (HtmlGenericControl)e.Item.FindControl("listItem");
myLi.Attributes.Add("class", myLi.Attributes["class"].ToString() + " yournewclass");
}
The ListView is comprised of the items which are defined by your ItemTemplate section, and not of the li elements. Therefore, when you get an element from the ListView by index, you would first need to find the li before you can add a class to it.
Therefore, you need to use FindControl method on the item to get the li.
Now, there are a few things wrong here.
ListView doesn't have an ElementAt method, it's Items collection has it, but still, I would use ul_HeaderMenu.Items[3] to get an element at an index.
If you want to use FindControl method, you need to add an id to your li inside your ItemTemplate which you will pass to FindControl to get the li.
AddControl method does not exist, you have to use Attributes collection on the li to change the class attribute. Here you have to be careful though since you want to keep the classes already there, so you'll have to concatenate the strings, but you don't want to add a same class multiple times, therefore it's best if you created a helper method AddClass that takes the string and returns it with the class added.
You can do all this at any point, but usually you'll want to use the ItemDataBound event, as described by Lars Anundskas in the meantime.
And lastly, while you're free to use any convention you like, personally I find your casing convention confusing - you can read a bit on Microsoft's suggestions here.

Dynamically assigning a property in a usercontrol in an ASP.NET repeater control

I currently have a repeater control and inside the itemtemplate I have a usercontrol. This usercontrol renders correctly, but I am trying to assign a dataitem to a property in the repeater control.
<asp:Repeater ID="Repeater1" DataSourceID="EntityDataSource" runat="server">
<ItemTemplate>
<uc1:Request ID="Request1" runat="server" RequestId='<%# Eval("RequestId") %>' />
</ItemTemplate>
RequestId is just an Int32. It just doesn't assign it.
I can put the eval outside of the usercontrol just in the itemtemplate and it correctly outputs the right id.
If I remove the whole eval and just type a number in then it works fine.
Any help appreciated.
[UPDATE] : Issue Solved
I was using an EntityDataSource and this automatically binded to the repeater. It printed out all the information from the database on the screen without any codebehind. But when I put in the code behind Repeater1.DataBind(); it then started to work.
I don't know why, but hey it's solved. It now successfully passes the value through. I imagine it has something to do with the page lifecycle.
If you just bind with repeater collection of int, you need use this:
<uc1:Request ID="Request1" runat="server" RequestId='<%# Container.DataItem %>' />
And don't forget to call DataBind() for repeater or for Page where there is a repeater control.
Are you missing a ' at the end?
change following:
RequestId='<%# Eval("RequestId") %> />
to
RequestId='<%# Eval("RequestId") %>' />
You can implement this by using Repeater control's ItemDataBound event, so that you can set the dynamic property for the control.

How to set a datasource on a nested control list on postback

I am trying here to set correctly a Datasource of a nested control list.
Basic idea :
I have an asp:repeater item. Inside there is a DropDownList and a BulletedList plus a Button.
I want to add the selected Item in the DropDownList from the selected row in the Repeater to be added into the selected row's BulletedList.
So far I managed to do that with OnItemDataBound and OnClick wich is quite good. The problem is the event OnClick is fired after OnItemDataBdound. To view then the Item I added in the BulletedList's datasource I have to refresh the page.
I tried this :
((BulletedList)src.FindControl("sharedPlanDomains")).Items.Clear();
and then
((BulletedList)src.FindControl("sharedPlanDomains")).Datasource = myobject;
((BulletedList)src.FindControl("sharedPlanDomains")).DataBind();
But it seems that it is not working.
((BulletedList)src.FindControl("sharedPlanDomains")).DomainsAssociated.ForEach(f => list.Items.Add(new ListItem { Text = f.Name }));
Doesn't work either.
Any suggestions available ?
[Edit: Clarifications]
Say I have this structure:
Hosting Plan : i-Perso
Domains : [The dropdownlist] [Button: Associate]
Associated Domains :
google.com
google2.com
Hosting Plan : i-Mense
Domains : [The dropdownlist] [Button: Associate]
Associated Domains :
google3.com
so let's take example that I click on the 1st dropdownlist and select the domain google4.com, then google4.com is going to be added in the datasource of the bulletedlist of the row i-Perso.
What I want to do here is to associate domains and plans. I would have done it better if it would be only a relationship of 1 - 1 but it's a relationshop of 1 - Multiple.
You can bind the datasource of your inner list view to a property of the items bound to your outer listview. However, to do that the inner listview as to be in the item template of the outer listview.
See the code below and note the DataSource='<%# Eval("Labels_color") %>' attribute for the inner list view.
<asp:ListView ID="ListView_Orp_Results" runat="server" ItemPlaceholderID="itemPlaceholder">
<LayoutTemplate>
<div id="outer_result_container">
<div id="itemPlaceholder" />
</div>
</LayoutTemplate>
<ItemTemplate>
<div id="result_photo">...</div>
<div id="result_category">...</div>
<div id="result_detector">...</div>
<div id="inner_result_container" runat="server">
<asp:ListView ID="ListView_inner_results" runat="server" ItemPlaceholderID="itemPlaceholder" DataSource='<%# Eval("Labels_color") %>'>
<LayoutTemplate>
<div id="outer_result_container" runat="server" >
<div id="itemPlaceholder" runat="server"> </div>
</div>
</LayoutTemplate>
<ItemTemplate>
<div id="inner_result_photo">...
</div>
<div id="inner_result_category">...
</div>
<div id="inner_result_categoryID">...
</div>
</ItemTemplate>
</asp:ListView>
</div>
</div>
</ItemTemplate>
</asp:ListView>
This way you don't need to bond the nested listview from the code behind. Just bind the main listview, and all inner listview will be automatically bound to the Labels_texture property of the bound objects
About the runat="server" it is a required attribute for asp.net controls. Basically, this attribute means that asp.net will parse the tag and create a corresponding object.
Most of the time you don't need it on html elements (div, p, ...) but under some circumstance you might want it to manipulate the corresponding object in your code behind.

Categories

Resources