ItemDataBound of repeater does not effect SOME OF THE values - c#

I have a repeater and have some labels and a button inside it. Here is my .aspx:
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="EntityDataSourceTeklifler" OnItemCommand="Repeater1_ItemCommand" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
<div class="panel panel-primary">
<div class="panel-body">
<strong>Teklif No.</strong> <asp:Label ID="lblTeklifNo" runat="server" Text='<%#Eval("TeklifId") %>'></asp:Label><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>Ürünler:</strong><br />
<%#Eval("TeklifSiparis") %>
<strong>Genel Toplam:</strong> <%#Eval("TeklifTutar") %>$<br />
<strong>Not:</strong><br />
<%#Eval("TeklifNot") %><br />
<strong>Teklif Durumu:</strong> <asp:Label ForeColor="Red" ID="lblApproved" runat="server" Text='<%# CheckIfApproved(Convert.ToBoolean(Eval("Approved"))) %>'></asp:Label><br /><br />
<asp:Button ID="btnAssignApproved" runat="server" Text="Satışa Döndü Olarak İşaretle" CssClass="btn btn-primary" CommandArgument='<%# Eval("TeklifId") %>' />
</div>
</div>
</ItemTemplate>
</asp:Repeater>
And my codebehind:
protected string CheckIfApproved(bool isApproved)
{
string result;
if (isApproved)
{
result = "Satışa Dönmüştür";
}
else
{
result = "Satışa Dönmemiştir";
}
return result;
}
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
string teklifId = e.CommandArgument.ToString();
TeklifTable teklif = entity.TeklifTable.Where(t => t.TeklifId == teklifId).FirstOrDefault();
teklif.Approved = true;
entity.SaveChanges();
Page_Load(null, EventArgs.Empty);
}
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item)
{
Label lbl = e.Item.FindControl("lblApproved") as Label;
Button btn = e.Item.FindControl("btnAssignApproved") as Button;
if (lbl.Text.Equals("Satışa Dönmüştür"))
{
btn.Visible = false;
lbl.ForeColor = System.Drawing.Color.Blue;
}
else
{
lbl.ForeColor = System.Drawing.Color.Purple;
}
}
}
As you can see my repeater changes label color and button visibility according to boolean attribute 'Approved' of my database. Approved attribute changes with the button click and there isn't any problem here. I am checking approved value if it is true or false and changes label according to it. Lastly ItemDataBound method changes label color and button visibility according to label which has been changed in checkIfApproved method.
Now, here is my problem. As you can see I defined default label color as red in .aspx. This should changed to blue or purple but SOME OF THE VALUES stays as red. That means 'Repeater1_ItemDataBound' method does not effect some of the values. Here is another interesting point: First item of repeater get effected as I want and displayed as blue or purple according to label text but second item comes red.That means second item does not get effected by this method. Third item get effected and fourth does not. This goes like this. Any ideas ?

The probelm with your code is that you are only checking if the item is a Item type but repeater control item consists of Item as well as AlternatingItem i.e. every alternating item acts falls under AlternatingItem of ListItemType.
Simply add this line in your ItemDataBound event:-
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
//your code here
}
}

Related

How to make button visible inside repeater?

Here I have kept two button(btnhide and btnunhide) and a label inside the repeater and I have made button btnunhide invisible initially. Now what I want is that as I press button btnhide then btnunhide which is invisible intially should be visible.
Solution Will Be great help.
Html used
<asp:Repeater ID="Repeater1" runat="server" OnItemCommand="Repeater1_ItemCommand" >
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<asp:Button ID="btn" CommandName="h" runat="server" Text="Hide" />
<asp:Button ID="btnhide" Visible="false" runat="server" Text="Unhide" />
</ItemTemplate>
</asp:Repeater>
Code behind
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "h")
{
}
}
You can achieve this by just a single button by changing the Text to hide/unhide and do the functionality as required by just checking the Text property of the button.
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "h")
{
Button btn = (Button)(e.CommandSource);
if(btn.Text == "hide")
{
btn.Text = "unhide";
//Do additional work here, when unhiding.
}
else
{
btn.Text = "hide";
//Do additional work here, when hiding.
}
}
}
I Hope, this helps. Thanks

Find Control Inside ListView Control

I want to find "Label" control with ID = "Label" inside the "ListView" control. I was trying to do this with the following code:
((Label)this.ChatListView.FindControl("Label")).Text = "active";
But I am getting this exception: Object reference not set to an instance of an object .
What is wrong here ?
This is aspx code:
<asp:ListView ID="ChatListView" runat="server" DataSourceID="EntityDataSourceUserPosts">
<ItemTemplate>
<div class="post">
<div class="postHeader">
<h2><asp:Label ID="Label1" runat="server"
Text= '<%# Eval("Title") + " by " + this.GetUserFromPost((Guid?)Eval("AuthorUserID")) %>' ></asp:Label></h2>
<asp:Label ID="Label" runat="server" Text="" Visible="True"></asp:Label>
<div class="dateTimePost">
<%# Eval("PostDate")%>
</div>
</div>
<div class="postContent">
<%# Eval("PostComment") %>
</div>
</div>
</ItemTemplate>
</asp:ListView>
Listview is a databound control; so controls inside it will have different ids for different rows. You have to first detect the row, then grab the control. Best to grab such controls is inside an event like OnItemDataBound. There, you can do this to grab your control:
protected void myListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
var yourLabel = e.Item.FindControl("Label1") as Label;
// ...
}
}
If you want to grab it in Page_Load, you will have to know specific row and retrieve the control as:
var theLabel = this.ChatListView.Items[<row_index>].FindControl("Label1") as Label;
This function will get Author Name from a database, you just need to call your method to get Author Name and then return it
protected string GetUserFromPost(Guid? x)
{
// call your function to get Author Name
return "User Name";
}
And to bind label in the list view you have to do it in list view ItemDataBound Event
protected void ChatListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
Label lbl = e.Item.FindControl("Label") as Label;
lbl.Text = "Active";
}
}
Here are the list view aspx code changes (just add onitemdatabound="ChatListView_ItemDataBound"):
asp:ListView
ID="ChatListView"
runat="server"
DataSourceID="EntityDataSourceUserPosts"
onitemdatabound="ChatListView_ItemDataBound"
It should be Label1 in the arguement:
((Label)this.ChatListView.FindControl("Label1")).Text = "active";
This should be in a databound event.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listview.itemdatabound.aspx
Try it:
protected void ChatListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item is ListViewDataItem)
{
var yourLabel = e.Item.FindControl("Label1") as Label;
// ...
}
}
One simple solution to this problem, which avoids the FindControl code is to place OnInit on your label.
This would change your page code to this: <asp:Label ID="Label" runat="server" Text="" Visible="True" OnInit="Label_Init"></asp:Label>
And in your code behind you will now have a function like this:
protected void Label_Init(object sender, EventArgs e)
{
Label lblMyLabel = (Label)sender;
lblMyLabel.Text = "My Text";
}

ASP.NET Repeater: Button in item template to redirect to another page

I have a repeater and each item contains a button which should redirect to another page and also pass a value in the query string.
I am not getting any errors, but when I click the button, the page just refreshes (so I am assuming a postback does occur) and does not redirect. I think that for some reason, it isn't recognizing the CommandName of the button.
Repeater code:
<asp:Repeater ID="MySponsoredChildrenList" runat="server" OnItemDataBound="MySponsoredChildrenList_ItemDataBound" OnItemCommand="MySponsoredChildrenList_ItemCommand">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<br />
<div id="OuterDiv">
<div id="InnerLeft">
<asp:Image ID="ProfilePic" runat="server" ImageUrl='<%#"~/Resources/Children Images/" + String.Format("{0}", Eval("Primary_Image")) %>'
Width='300px' Style="max-height: 500px" /></div>
<div id="InnerRight">
<asp:HiddenField ID="ChildID" runat="server" Value='<%# DataBinder.Eval(Container.DataItem, "Child_ID") %>'/>
<span style="font-size: 20px; font-weight:bold;"><%# DataBinder.Eval(Container.DataItem, "Name") %>
<%# DataBinder.Eval(Container.DataItem, "Surname") %></span>
<br /><br /><br />
What have you been up to?
<br /><br />
<span style="font-style:italic">"<%# DataBinder.Eval(Container.DataItem, "MostRecentUpdate")%>"</span>
<span style="font-weight:bold"> -<%# DataBinder.Eval(Container.DataItem, "Update_Date", "{0:dd/MM/yyyy}")%></span><br /><br /><br />Sponsored till:
<%# DataBinder.Eval(Container.DataItem, "End_Date", "{0:dd/MM/yyyy}")%>
<br /><br />
<asp:Button ID="ChildProfileButton" runat="server" Text="View Profile" CommandName="ViewProfile" />
</div>
</div>
<br />
</ItemTemplate>
<SeparatorTemplate>
<div id="SeparatorDiv">
</div>
</SeparatorTemplate>
</asp:Repeater>
C# Code behind:
protected void MySponsoredChildrenList_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
// Stuff to databind
Button myButton = (Button)e.Item.FindControl("ChildProfileButton");
myButton.CommandName = "ViewProfile"; }
}
protected void MySponsoredChildrenList_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "ViewProfile")
{
int ChildIDQuery = Convert.ToInt32(e.Item.FindControl("ChildID"));
Response.Redirect("~/ChildDescription.aspx?ID=" + ChildIDQuery);
}
}
I am new to using repeaters so it's probably just a rookie mistake. On a side note: is there a better way of obtaining the ChildID without using a hidden field?
EDIT: Using breakpoints; the ItemDatabound event handler is being hit, but the ItemCommand is not being entered at all
You need to set MySponsoredChildrenList_ItemDataBound as protected. Right now, you have just 'void' which by default is private, and is not accessible to the front aspx page.
Another way is to use the add event handler syntax from a function in your code behind, using the += operator.
Either way, the breakpoint will now be hit and our code should mwork.
EDIT: So the above solved the compilation error but the breakpoints are not being hit; I've ran some tests and am able to hit breakpoints like this:
Since I do not know how you are databinding, I just added this code to my code-behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
MySponsoredChildrenList.DataSource = new List<object>() { null };
MySponsoredChildrenList.DataBind();
}
}
Note: If you DataBind() and ItemDataBound() is called on every postback, it will wipe out the command argument, which is potentially what you are seeeing; so if you always see [object]_ItemDataBound() breakpoint hit, but never [object]_ItemCommand(), it is because you need to databind only on the initial page load, or after any major changes are made.
Note also the method MySponsoredChildrenList_ItemCommand doesn't work:
protected void MySponsoredChildrenList_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "ViewProfile")
{
int ChildIDQuery = Convert.ToInt32(e.Item.FindControl("ChildID"));
Response.Redirect("~/ChildDescription.aspx?ID=" + ChildIDQuery);
}
}
When you do FindControl, you need to cast to the correct control type, and also make sure to check for empty and null values before converting, or else you will possibly have errors:
protected void MySponsoredChildrenList_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "ViewProfile")
{
int childId = 0;
var hiddenField = e.Item.FindControl("ChildID") as HiddenField;
if (null != hiddenField)
{
if (!string.IsNullOrEmpty(hiddenField.Value))
{
childId = Convert.ToInt32(hiddenField.Value);
}
}
if (childId > 0)
{
Response.Redirect("~/ChildDescription.aspx?ID=" + childId);
}
}
}
Hope this helps - if not, please post additional code for the "full picture" of what is happening, so we can see where else you might have a problem.
I think on the repeater you need to add
OnItemDataBound="MySponsoredChildrenList_ItemDataBound"
Not 100% sure, but could be the same for the ItemCommand.
--
In regards to obtaining the ChildID. Add a CommandArgument to the button in the repeater, and set it in the same way, <% Eval("ChildID") %>. This can the be obtained using e.CommandArgument.
Try this.. Add an attribute to item row
row.Attributes["onclick"] = string.Format("window.location = '{0}';", ResolveClientUrl(string.Format("~/YourPage.aspx?userId={0}", e.Item.DataItem)) );
or You can do like this also
<ItemTemplate> <tr onmouseover="window.document.title = '<%# Eval("userId", "Click to navigate onto user {0} details page.") %>'" onclick='window.location = "<%# ResolveClientUrl( "~/YourPage.aspx?userId=" + Eval("userid") ) %>"'> <td> <%# Eval("UserId") %> </td> </tr> </ItemTemplate>

Problem with a hyperlink

I put a hyperlink inside a datalist..
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server">'<%# Eval("ThreadTitle") %>'</asp:HyperLink>
<br />
<br />
</ItemTemplate>
I want it to enable it to be pressed so that the datalist event will be triggered and transfer me to another page:
protected void DataList1_SelectedIndexChanged(object sender, EventArgs e)
{
Server.Transfer("AnswerQuestion.aspx?x=" + DataList1.DataKeyField + "&question=" + DataList1.SelectedValue + "&time=" + DateTime.Now);
}
Unfortunately, the link seems to be disabled and I cant press on it to trigger the DataList Selected event..
How can I make the hyperlink active ?
If you want to trigger a selecteditemchaned event use a LinkButton instead of hyperlink.
<asp:DataList ID="DataList1" runat="server"
onselectedindexchanged="DataList1_SelectedIndexChanged">
<ItemTemplate>
<asp:LinkButton ID="sjdj" runat="server" CommandName="Select">
<%# Container.DataItem %></asp:LinkButton>
</ItemTemplate>
</asp:DataList>
In the code behind have
protected void DataList1_SelectedIndexChanged(object sender, EventArgs e)
{
Server.Transfer("~/jjtestjj.aspx?" + DataList1.DataKeyField);
}
why arent you using the Hyperlink as a hyperlink?
You can set the NavigationURL and Text using the OnItemDataBound (or equivalent) event.
this code works with an asp:Repeater:
protected void Row_DataItem(object row, RepeaterItemEventArgs args)
{
if (args.Item.ItemType == ListItemType.AlternatingItem || args.Item.ItemType == ListItemType.Item)
{
var item = (DataItemPOCO)args.Item.DataItem;
var link = (HyperLink)args.Item.FindControl("HyperLink1");
link.Text = item.LinkText;
link.NavigateUrl = item.URL;
}
}

C# Pass textbox content via CommandArgument in Repeater

<asp:Repeater ID="Cartridges" runat="server" onitemcommand="Cartridges_ItemCommand">
<ItemTemplate>
<p class="cartprice"><%#String.Format("{0:C}", Eval("Price"))%></p>
<hr class="hr4" />
<p class="cartqty">QTY <asp:TextBox ID="cartQty" Text="0" runat="server"></asp:TextBox> </p>
<div class="cartbuy2"><asp:LinkButton ID="buy" runat="server" CommandName="AddtoCart" CommandArgument=<%#Eval("cartID") %> Text="Buy"></asp:LinkButton></div>
</ItemTemplate>
</asp:Repeater>
How can I pass the textbox value within CommandArgument? Sorry totally lost...
Did you try: CommandArgument='<%#Eval("cartID") %>'
this is different from yours as it is surrounded by a single quote, I guess this is the correct syntax.
Use FindControl to get other items in the repeater Item. For Example:
protected void repeater_ItemCommand(object sender, RepeaterCommandEventArgs e)
{
LinkButton lb = (LinkButton)e.CommandSource;
string textBoxValue = ((TextBox)lb.Parent.FindControl("cartQty")).Text;
}
you need to bind the cartId to the linkbutton onItemDataBound and then access it onItemCommand, I have modified code for you, give this a go
<asp:Repeater ID="Cartridges" runat="server" onitemcommand="Repeater_OnItemCommand" OnItemDataBound="Repeater_OnItemDataBound">
<ItemTemplate>
<p class="cartprice"><%#String.Format("{0:C}", Eval("Price"))%></p>
<hr class="hr4" />
<p class="cartqty">QTY <asp:TextBox ID="cartQty" Text="0" runat="server"></asp:TextBox> </p>
<div class="cartbuy2"><asp:LinkButton ID="buy" runat="server" CommandName="AddtoCart" Text="Buy"></asp:LinkButton></div>
your onItemdatabound should look like this
protected void Repeater_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
//your code...
LinkButton add = (LinkButton)e.Item.FindControl("buy");
add.CommandArgument = cartID.ToString();
}
and then you can access the text box on item command like this
protected void Repeater_OnItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "AddtoCart")
{
LinkButton btnEdit = (LinkButton)e.CommandSource;
if (btnEdit != null)
{
string editId = btnEdit.CommandArgument;
string text = ((TextBox)e.Item.FindControl("cartQty")).Text;
//do some stuff with your cartid and quantity
}
}
}
You can also extend your code with edit/delete command arguments by adding more linkbuttons and binding them to the correct command and then accessing them in on item command
Thanks

Categories