Respond to Button Events inside Repeater ItemTemplate - asp.net

so i have removed the datasouce and just have DataBind() then my page is still blowing and refreshing the page and not in a EDIT mode.
what i am trying to do is when the user click on Edit button then make it inline editing the repeater row.
END UPDATE
onItemCommand i have added DataBind()
rpt.DataSource = mydatasource;
rpt.DataBind();
after i do that my page is not in edit mode and it blow away and everyting is refreshed
i have on page_load
if (!IsPostBack)
{
rpt.DataSource = mydatasource;
rpt.DataBind();
}
end update
I've used repeaters many times without problems but something is going on here. I have a repeater and I'm subscribing to the itemDatabound event, But when i click the button (which is a linkbutton inside my repeater itemtemplate) it does not go to the ItemDataBound
<asp:Repeater ID="rpt" runat="server" OnItemCommand="rpt_OnItemCommand" OnItemDataBound="rpt_OnItemDataBound">
<ItemTemplate>
<li>
<asp:Label ID="Label" runat="server" />
<asp:LinkButton ID="LinkButton1" runat="server" CommandName="edit" CommandArgument='<%# Eval("MyID") %>'
Text='<%# Eval("Title") %>' />
</li>
</ItemTemplate>
</asp:Repeater>
protected void rpt_OnItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "delete")
{
//Data.Contacts.RemoveAt(e.Item.ItemIndex);
}
else if (e.CommandName == "edit")
{
EditIndex = e.Item.ItemIndex;
}
else if (e.CommandName == "save")
{
//
}
}
protected void rpt_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if (e.Item.ItemIndex == EditIndex)
{
// never come to this line.... after the user click on LinkButton
}
}
}

Don't know if this helps but you must call DataBind() in order for for the OnItemDataBound event to fire. Also my guess is you are trying to set the EditIndex in the OnItemCommand and then use the value in the OnDataBind event. The events fire in the order OnItemDataBound then OnItemCommand so the EditIndex wouldn't be correct anyway in that situation.
Add rpt.DataBind to the OnItemCommand. This workded when I tried it from your code, NOTE that you will be binding twice if you aren't using !IsPostBack for original data bind.
rpt.DataSource = strings;
if (!IsPostBack)
{
rpt.DataBind();
}
protected void rpt_OnItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "delete")
{
//Data.Contacts.RemoveAt(e.Item.ItemIndex);
}
else if (e.CommandName == "edit")
{
EditIndex = e.Item.ItemIndex;
}
else if (e.CommandName == "save")
{
//
}
rpt.DataBind();
}

You must change your rpt_OnItemCommand function.
protected void rpt_OnItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "delete")
{
//Data.Contacts.RemoveAt(e.Item.ItemIndex);
}
else if (e.CommandName == "edit")
{
EditIndex = e.Item.ItemIndex;
}
else if (e.CommandName == "save")
{
//
}
else if (e.CommandName == "Complete")
{
// your function goes here
}
}

Why do you think that the ItemDataBound is raised when you click your LinkButton? ItemDataBound is only fired when Repeater.DataBind() is called.
Actually the repeater's ItemCommand event is raised instead.

I'm a little confused, but from the example above it looks like you've got it backwards. The button click would never fire the ItemDataBound event. The ItemDataBound event is only called after each item is bound to the repeater.
The button click should fire the ItemCommand event however, and if that's not happening I would check to make sure you've actually assigned the ItemCommand handler, and also make sure that the command name is valid.
On a side note, this behavior can also happen when the repeater is bound at every postback. Make sure that you're binding the repeater when !Page.IsPostBack.

Related

Find Linkbutton in Repeater Itemtemplate when on page load

I'm using a LinkButton in Repeater ItemTemplate but if my LinkButton is NULL then I don't want to show this Linkbutton. Can I control this LinkButton on Page Load?
<asp:Repeater ID="rptSlider" runat="server" >
<ItemTemplate>
<li>
.....
<asp:LinkButton ID="lb_url" PostBackUrl='<%#Eval("button_url") %>' runat="server">Go</asp:LinkButton>
...
</li>
</ItemTemplate>
Try this way in page-load event
LinkButton linkButton= (LinkButton)Repeater1.Items[0].FindControl("lb_url");
linkButton.Visible = false;
but I will suggest to use ItemDataBound event to set visibility of link-button.
protected void repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
var linkButton= e.Item.FindControl("lb_url") as LinkButton;
// set link-button visibility
}
}
You may check the same under ItemCommand. Please check whether the following code works or not.
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
string url=((LinkButton)e.CommandSource).Text;
if (string.IsNullOrEmpty(url))
((LinkButton)e.CommandSource).Visible=false;
else
((LinkButton)e.CommandSource).Visible=true;
}

Gridview RowCommand arguments not passing correctly in Safari

I have an asp page with a gridview on. I have also added a clientscript to each bound row to highlight/un-higlight on mouse over/out. I have added an asp:button as a templatefield and bound a value to the CommandArgument. In IE and FIrefox I get the expected behaviour where the CommandName is passed to the _RowCommand event. However, when in Safari I only ever see the CommanName of "Select" passed to RowCommand.
The expected behaviour is that when a bound row is clicked the "Select" paramater is passed to the RowCommand event. When the Button in the row is clicked the argument "Remove" is passed.
protected void gvContacts_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Attributes.Add("onMouseOver", "Highlight(this)");
e.Row.Attributes.Add("onMouseOut", "UnHighlight(this)");
e.Row.Attributes["onclick"] = Page.ClientScript.GetPostBackClientHyperlink(gvContacts, "Select$" + e.Row.RowIndex);
e.Row.Attributes["style"] = "cursor:pointer";
}
}
protected void gvContacts_RowCommand(object sender, GridViewCommandEventArgs e)
{
switch (e.CommandName) //Always "Select" when browser is Safari.
{
case "Select":
Session["clientID"] = gvContacts.Rows[Convert.ToInt32(e.CommandArgument)].Cells[0].Text;
Response.Redirect("../Contacts/ContactEdit.aspx?readin=1");
break;
case "Remove":
//Remove the client from the list
Company company = new Company();
company.Get(Int32.Parse(Session["CompanyID"].ToString()), ((Model)Session["model"]).ConnectionString);
company.RemoveUser(Int32.Parse(e.CommandArgument.ToString()));
BindGrid(company.ID);
break;
}
}
HTML for itemtemplate
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnRemove" runat="server" Text="Remove" CommandName="Remove" OnClientClick="return confirmRemove();"
CommandArgument='<%# Eval("ID") %>' />
</ItemTemplate>
Any thoughts would be appreciated. Thanks
I think You should First Check that Button was clicked From which browser and if it was from safari than Change Command Name ..
protected void gvContacts_RowCommand(object sender, GridViewCommandEventArgs e)
{
System.Web.HttpBrowserCapabilities browser = Request.Browser;
if(browser.Browser=="Safari") //Check The Browser
{
e.CommandName="Select";
}
switch (e.CommandName) //Always "Select" when browser is Safari.
{
case "Select":
Session["clientID"] = gvContacts.Rows[Convert.ToInt32(e.CommandArgument)].Cells[0].Text;
Response.Redirect("../Contacts/ContactEdit.aspx?readin=1");
break;
case "Remove":
//Remove the client from the list
Company company = new Company();
company.Get(Int32.Parse(Session["CompanyID"].ToString()), ((Model)Session["model"]).ConnectionString);
company.RemoveUser(Int32.Parse(e.CommandArgument.ToString()));
BindGrid(company.ID);
break;
}
}

How to hide a control inside user control after click gridview button

This is the problem that bothers me for the past few days
I have a page with couple user controls.
On that page, there is a grid. If a user click on a particular row, a control (li) on the user control is shown or hidden based on the condition.
What makes things complicate is the user control and grid grid are all inside the update panel, but another user control is outside updaet panel
In the rowcommand event, I assigned a Session variable, dontshow. Based on the criteria, dontshow variable will be assigned to true or false. Then the control on the user control will be shown or hidden based on dontshow condition
So far, I am encountering the problem.
let's say (li) control was shown, but after the user click gridview, dontshow is set to true. (li) control should be hidden. No it does not. I have to click other button to do postback to make it happen
The same is true for the usercontrol outside the update panel. The logic is similar
Over the past few days, I have found out that I can't set visible property of controls in user control at page_load because that happens after rowcommand event. I moved the code to pre_render event
I even tried to use different control such as placeholder, panel, etc. That still does not work
I also trace the code. The pre_render event comes after row command. dontshow variable is false. The (li) control visible is set to false. However, after rendering, I can still see the control
What should I do?
Below are the snapshot of the codes
Thank you for the help
main.aspx
.....
<%# Register Src="../usercontrol1.ascx" TagPrefix="uctest1" TagName="ctrl1" %>
<%# Register Src="../usercontrol2.ascx" TagPrefix="uctest2" TagName="ctrl2" %>
...
<ctrl1:uctest1runat="server" ID="test1" />
<asp:UpdatePanel ID="updatepantest1" runat="server" UpdateMode="Always">
<ContentTemplate>
<uctest2:ctrl2runat="server" UpdateMode="Conditional" ID="test2" />
....
<asp:GridView ...>
//grid where rowcommand was executed
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
main.aspx code behind
protected void gridview_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "something")
{
.....
if (x = 1)
session["dontshow"] = true
else
session["dontshow"] = false
}
}
user control aspx (usercontrol1)
....
<ul>
<li id="li1" runat="server">
<asp:label>this is test</asp:label>
</li>
<li >
<asp:label>this is test</asp:label>
</li>
<li >
<asp:label>this is test</asp:label>
</li>
</ul>
....
user control code behind (usercontrol1)
protected void Page_PreRender(object sender, EventArgs e)
{
bool dontshow = false;
if (Session["dontshow"] != null)
{
dontshow = (bool)Session["dontshow"]
}
if (dontshow)
li1.visible = false
else
li1.visible = true
}
user control aspx (usercontrol2)
....
<asp:PlaceHolder ID="placeholder1" runat="server">
<asp:label ID="label1" runat="server"></asp:label>
</asp:PlaceHolder>
....
user control code behind (usercontrol2)
protected void Page_PreRender(object sender, EventArgs e)
{
bool dontshow = false;
if (Session["dontshow"] != null)
{
dontshow = (bool)Session["dontshow"]
}
if (dontshow)
{
label1.visible =false;
}
else
{
label1.visible =true;
label1.Text ="this is test";
}
}
You could do it in your Row command like this
protected void gridview_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "something")
{
.....
var viewRow = (GridViewRow)(((ImageButton)e.CommandSource).NamingContainer);
HtmlGenericControl li1 = (HtmlGenericControl)viewRow.FindControl("li1");
if (x = 1)
{
session["dontshow"] = true;
li1.Visible = true;
}
else
{
session["dontshow"] = false;
li1.Visible = false;
}
}
}
Or, if you want to hide the control during data bound you could do it like this
protected void gridview_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
HtmlGenericControl li1 = (HtmlGenericControl)e.Row.FindControl("li1");
if (dontshow)
li1.visible = false;
else
li1.visible = true;
}
}
Hope this helps :-)

Repeater with Buttons doesn't fire OnItemCommand even when DataBind doesn't happen when IsPostBack is true

I've got an image button in a Repeater, which is in a User Control, and I can't get the OnItemCommand event to fire when I click it. It always gives the error: "... Invalid postback or callback argument. Event validation is enabled using ..."
When I change the image button to a link button, it doesn't give me the error, but it still doesn't fire the OnItemCommand function.
I found some other relevant answers (such as How to process events from Buttons inside Repeaters? And what's this EnableEventValidation thing?) but they all say, "Make sure you're data-binding your repeater inside of a if(!Page.IsPostBack) block." I have done that, but it didn't make a difference.
Here's the markup for the repeater:
<asp:Repeater ID="rptExpenses" OnItemDataBound="rptExpenses_ItemDataBound" OnItemCommand="Button_Command" runat="server" >
<ItemTemplate>
<asp:ImageButton ID="ibDelete" ImageUrl="~/Images/delete.png" CommandName="Delete" runat="server" />
</ItemTemplate>
</asp:Repeater>
Here's some exerpts from the code-behind
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
rptExpenses.DataSource = ExpenseIds;
rptExpenses.DataBind();
}
}
protected void rptExpenses_ItemDataBound(object sender, RepeaterItemEventArgs e) {
if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem)) {
var ibDelete = (ImageButton)e.Item.FindControl("ibDelete");
ibDelete.CommandArgument = e.Item.DataItem.ToString();
}
}
protected void Button_Command(object sender, EventArgs e) {
var btn = (IButtonControl)sender;
switch (btn.CommandName) {
case "Delete":
//delete it
break;
}
}
Try using this code instead:
<asp:Repeater ID="rptExpenses" runat="server">
<ItemTemplate>
<asp:ImageButton ID="ibRemove" ImageUrl="~/Images/delete.png" runat="server"
CommandName="Remove"
CommandArgument='<%# Container.DataItem %>'
OnCommand="ibRemove_Click"/>
</ItemTemplate>
</asp:Repeater>
And this in the code behind:
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
rptExpenses.DataSource = ExpenseIds;
rptExpenses.DataBind();
}
}
protected void ibRemove_Click(object sender, CommandEventArgs e)
{
var btn = (IButtonControl)sender;
switch (btn.CommandName)
{
case "Remove":
//delete it, use btn.CommandArgument to find id to remove
break;
}
}
If you still receive the ... Invalid postback or callback argument. Event validation is enabled using ... error, it most likely means that you are somewhere re-binding the repeater before the ibRemove_Click(...) event is raised.
I found the reason why this was happening in the answer to this question: Why ItemCommand doesn't fired on My Repeater
Turns out that for some reason the Page's DataBind function was invalidating the repeater's controls without passing through the repeater's OnItemDataBound function a second time.

Why is the footer-item not included in Repeater.Items?

I need to get a value from a textbox inside a FooterTemplate in the OnClick event of a button. My first thought was to loop through the items-property on my repeater, but as you can see in this sample, it only includes the actual databound items, not the footer-item.
ASPX:
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
Item<br />
</ItemTemplate>
<FooterTemplate>
Footer<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:Repeater>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
Code-behind.cs:
protected void Page_Load(object sender, EventArgs e)
{
ListItemCollection items = new ListItemCollection();
items.Add("value1");
items.Add("value2");
Repeater1.DataSource = items;
Repeater1.DataBind();
}
protected void Button1_Click(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine(Repeater1.Items.Count);
}
This code will only output "2" as the count, so how do I get to reference my textbox inside the footertemplate?
From the MSDN documentation, the Items is simply a set of RepeaterItems based off the DataSource that you are binding to and does not include items in the Header or FooterTemplates.
If you want to reference the textbox, you can get a reference on ItemDataBound event from the repeater where you can test for the footer.
E.g.
private void Repeater_ItemDataBound(Object Sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Footer)
{
TextBox textBox = e.Item.FindControl("TextBox1") as TextBox;
}
}
You can find controls in the repeater. That will give you all the controls in the repeater (RepeaterItems collection). Now you can do something like this:
RepeaterItem footerItem=null;
foreach(Control cnt in Repeater1.Controls)
{
if(cnt.GetType() == typeof(RepeaterItem) && ((RepeaterItem)cnt).ItemType == ListItemType.Footer)
{
footerItem = cnt;
break;
}
}
The footer should be the last child control of the repeater so you can do something like..
RepeaterItem riFooter = Repeater1.Controls[Repeater1.Controls.Count - 1] as RepeaterItem;
if (riFooter != null && riFooter.ItemType == ListItemType.Footer) {
TextBox TextBox1 = riFooter.FindControl("TextBox1") as TextBox;
if (TextBox1 != null) {
TextBox1.Text = "Test";
}
}

Resources