Here is the situation I have, I have a repeater inside a Usercontrol.
The datasource is a IEnumerable<Investor> Exposed through a UserControl's Property.
I have overridden the UserControl's databind event to set the Repeater Datasource before databinding the repeater.
When it's not a postback, it databinds find and the events on the repeater item's controls fires up fine.
But there is one event on repeater items (Delete Investor) which call back the DataBind of the UserControl after removing the Investor from de datasource. When this Event is called, it does all the work (deleting the investor and so on...) calls back the
usercontrol's databind but when (within the usercontrol databind) the repeater is databinded again, the repeater items doesn't update (repeater items for investor not on the DataSource anymore still appears). My ItemDataBind doesn't even fire by then.
It is not obvious why DataBind of the Repeater should be called after PostBack - this part of the code is missed within your quotes - could you please either provide it for us or ensure that you don't have something like "if (!IsPostBack) userControl.DataBind();".
I haven't figured it out yet but I found something wierd.
If i watch the IsPostBack Property, when I step through the code on my usercontrol (on an actual postback) it is set to true.
Once my usercontrol code calls the event delegate, the method on my page hooked to this event fires and within this method, the IsPostBack property is false.
So it looks like the method on my page are called within another scope or something...?!
I don't see why the item should be deleted? What is the storage you are using for management of your data?
Are you sure that the item you see is indeed deleted from this storage?
From the code above it doesn't matter what the value of IsPostBack is during the code execution because it will invoke the DataBind for the same source (within Page_Load and InvestorDeleted event handlers).
I figured out what the problem is but I still can't understand why.
My solution is to use the sender (within the InvestorDeleted handler) instead of the investirList. Seems that, in that sequence, the page's investorList control is not the same instance as the sender.
I am wondering why do you have the troubles with binding because it seems that for any binding within your code the same data source is used - thus in case the entry is indeed deleted you can't see after any DataBind execution (it doesn't matter for which
instance you executed it).
Question which I still have - do you use SQL server for storage the data? Did you check that the entry is deleted from the database? Did you check that the object which you are using for DataBind (everywhere as I see!) is indeed updated with the entry deleting
change?
In this flow, the data is only stored on the SessionState. the data is persisted on a SaveButton_Click (on my master page)
But I figured out what happens... On my usercontrol, i when I was saving my control state, i was saving the handler registered along with it. So when I was reloading my state (on postback) i was reassigning the event handler of the Get instance of my page.
So then, within my handler, when I was setting the DataSource or Databinding my list, it would set it to the instance of my Get, databinding the list on the same instance, but the Instance of my page for the Post was staying untouched.
bigtrend
Did you check that the entry is deleted from the database? Did you check that the object which you are using for DataBind (everywhere as I see!) is indeed updated with the entry deleting change?
The data on the SessionState was updated, it was only the repeater that wouldn't bind on my updated version (it actually didn't rebind at all since It was binding the previous page's (get) repeater)
Thanks for your help!
The point of the story is, never keep handlers on any controlstate
Marked as answer by fireout on Jan 29, 2010 01:51 PM
fireout
Member
12 Points
8 Posts
Repeater DataBind not updating Items in Datasource
Jan 28, 2010 01:41 PM|LINK
Here is the situation I have, I have a repeater inside a Usercontrol.
The datasource is a IEnumerable<Investor> Exposed through a UserControl's Property.
I have overridden the UserControl's databind event to set the Repeater Datasource before databinding the repeater.
When it's not a postback, it databinds find and the events on the repeater item's controls fires up fine.
But there is one event on repeater items (Delete Investor) which call back the DataBind of the UserControl after removing the Investor from de datasource. When this Event is called, it does all the work (deleting the investor and so on...) calls back the usercontrol's databind but when (within the usercontrol databind) the repeater is databinded again, the repeater items doesn't update (repeater items for investor not on the DataSource anymore still appears). My ItemDataBind doesn't even fire by then.
Here is simplified markup:
<asp:Repeater ID="rptInvestors" runat="server" OnItemDataBound="rptInvestors_ItemDataBound" OnItemCommand="rptInvestor_ItemCommand"> <HeaderTemplate> <table class="datatable"> <thead> <tr> <asp:Repeater ID="rptFields" runat="server" OnItemDataBound="rptFields_ItemDataBound"> <ItemTemplate> <th><asp:Label ID="lblFieldName" runat="server"></asp:Label></th> </ItemTemplate> </asp:Repeater> <th> </th> </tr> </thead> </HeaderTemplate> <ItemTemplate> <tr> <asp:Repeater ID="rptFields" runat="server" OnItemDataBound="rptFields_ItemDataBound"> <ItemTemplate> <td><asp:Label ID="lblFieldValue" runat="server"></asp:Label><aaa:TextBox ID="txtFieldValue" runat="server" Visible="false"> </aaa:textbox> </asp:Label></td> </ItemTemplate> </asp:Repeater> <td style="text-align:right;"> <asp:LinkButton ID="lnkEdit" runat="server"><asp:Image ID="imgEdit" runat="server" /></asp:LinkButton> <asp:LinkButton ID="lnkDelete" runat="server"><asp:Image ID="imgDelete" runat="server" /></asp:LinkButton> <div id="investorEditorDiv" runat="server" class="hidden"> <div class="formrow" id="relationField" runat="server"> <div class="formlabel"> <asp:Label id="lblRelation" runat="server" Text="<%$ Resources: field.investor, relationType %>"></asp:Label> </div> <div class="formfield"> <asp:DropDownList ID="ddlRelationTypes" runat="server"></asp:DropDownList> </div> </div> <aaa:InvestorEditor id="investorEditor" runat="server"></aaa:InvestorEditor> </div> </td> </tr> </ItemTemplate> <FooterTemplate> <tr> <td colspan="<%# ViewDefinition.DocumentElement.ChildNodes.Count + 1 %>" style="text-align:right;"> <asp:LinkButton ID="lnkEdit" runat="server"><asp:Image ID="imgEdit" runat="server" /></asp:LinkButton> <div id="investorEditorDiv" runat="server" class="hidden"> <div class="formrow" id="relationField" runat="server"> <div class="formlabel"> <asp:Label id="lblRelation" runat="server" Text="<%$ Resources: field.investor, relationType %>"></asp:Label> </div> <div class="formfield"> <asp:DropDownList ID="ddlRelationTypes" runat="server"></asp:DropDownList> </div> </div> <aaa:InvestorEditor id="investorEditor" runat="server"></aaa:InvestorEditor> </div> </td> </tr> </table> </FooterTemplate> </asp:Repeater>and code bedind
public event EventHandler<EntityEventArgs> InvestorAdded; public event EventHandler<EntityEventArgs> InvestorDeleted; public override void DataBind() { rptInvestors.DataBind(); } public IEnumerable<Investor> DataSource { get { return rptInvestors.DataSource as IEnumerable<Investor>; } set { rptInvestors.DataSource = value; } } public Investor RootInvestor { get; set; } private Investor _investorCursor; protected void rptInvestors_ItemDataBound(object sender, RepeaterItemEventArgs e) { _investorCursor = e.Item.DataItem as Investor; Repeater rptFields = (Repeater)e.Item.FindControl("rptFields"); if (rptFields != null) { rptFields.DataSource = ViewDefinition.DocumentElement.ChildNodes; rptFields.DataBind(); } HtmlGenericControl relationField = (HtmlGenericControl)e.Item.FindControl("relationField"); if (relationField != null && RootInvestor == null) relationField.Visible = false; if (RootInvestor != null) { DropDownList ddlRelationTypes = (DropDownList)e.Item.FindControl("ddlRelationTypes"); if (ddlRelationTypes != null) { ddlRelationTypes.FillEnumList<InvestorRelationType>(r => ((int)r).ToString(), r => GetGlobalResourceObject("tblInvestorRelationTypes-Name", ((int)r).ToString()).ToString()); if (_investorCursor is RelatedInvestor) ddlRelationTypes.SelectedValue = ((int)(((RelatedInvestor)_investorCursor).RelationType)).ToString(); } } InvestorEditorControl investorEditor = (InvestorEditorControl)e.Item.FindControl("investorEditor"); if (investorEditor != null) { investorEditor.Investor = _investorCursor; } HtmlGenericControl investorEditorDiv = (HtmlGenericControl)e.Item.FindControl("investorEditorDiv"); LinkButton lnkEdit = (LinkButton)e.Item.FindControl("lnkEdit"); if (lnkEdit != null && investorEditorDiv != null) { if (e.Item.ItemType == ListItemType.Footer) { lnkEdit.Attributes["onclick"] = "showModal('#" + investorEditorDiv.ClientID + "', function(){ __doPostBack('" + lnkEdit.UniqueID + "', ''); }); pleaseWait(false); return false;"; lnkEdit.CommandName = "create"; } else lnkEdit.Attributes["onclick"] = "showModal('#" + investorEditorDiv.ClientID + "'); pleaseWait(false); return false;"; } Image imgEdit = (Image)e.Item.FindControl("imgEdit"); if (imgEdit != null) { if (e.Item.ItemType == ListItemType.Footer) imgEdit.ImageUrl = "~/image.ashx?icon-add.png"; else imgEdit.ImageUrl = "~/image.ashx?editPen.png"; } LinkButton lnkDelete = (LinkButton)e.Item.FindControl("lnkDelete"); if (lnkDelete != null) { lnkDelete.Attributes["onclick"] = "confirmLink(this, " + AntiXss.JavaScriptEncode(string.Format(GetLocalResourceObject("confirmDelete").ToString(), _investorCursor.FirstName + " " + _investorCursor.LastName), true) + "); return false;"; lnkDelete.CommandName = "delete"; lnkDelete.CommandArgument = _investorCursor.Id.ToString(); } Image imgDelete = (Image)e.Item.FindControl("imgDelete"); if (imgDelete != null) imgDelete.ImageUrl = "~/image.ashx?icon-delete.png"; } protected void rptFields_ItemDataBound(object sender, RepeaterItemEventArgs e) { ... } protected void lnkEdit_Click(object sender, EventArgs e) { LinkButton lnkEdit = sender as LinkButton; if (lnkEdit != null) { InvestorEditorControl investorEditor = (InvestorEditorControl)lnkEdit.Parent.FindControl("investorEditor"); Investor newInvestor = RootInvestor == null ? Investor.Create<Investor>() : RelatedInvestor.Create<RelatedInvestor>(); if (RootInvestor != null) { DropDownList ddlRelationTypes = (DropDownList)lnkEdit.Parent.FindControl("ddlRelationTypes"); ((RelatedInvestor)newInvestor).RelationType = (InvestorRelationType)(Convert.ToInt32(ddlRelationTypes.SelectedValue)); RootInvestor.RelatedInvestors.Add(newInvestor); } investorEditor.ReadControls(newInvestor); if (InvestorAdded != null) InvestorAdded.Invoke(this, new EntityEventArgs(newInvestor)); } } protected void lnkDelete_Click(object sender, EventArgs e) { LinkButton lnkDelete = sender as LinkButton; if (lnkDelete != null) { Investor targetInvestor = DataSource.Where(i => i.Id == Convert.ToInt32(lnkDelete.CommandArgument)).FirstOrDefault(); if (InvestorDeleted != null) InvestorDeleted.Invoke(this, new EntityEventArgs(targetInvestor)); } } protected void rptInvestors_ItemCommand(object source, RepeaterCommandEventArgs e) { if (e.CommandName == "create") { InvestorEditorControl investorEditor = (InvestorEditorControl)e.Item.FindControl("investorEditor"); Investor newInvestor = RootInvestor == null ? Investor.Create<Investor>() : RelatedInvestor.Create<RelatedInvestor>(); if (RootInvestor != null) { DropDownList ddlRelationTypes = (DropDownList)e.Item.FindControl("ddlRelationTypes"); ((RelatedInvestor)newInvestor).RelationType = (InvestorRelationType)(Convert.ToInt32(ddlRelationTypes.SelectedValue)); RootInvestor.RelatedInvestors.Add(newInvestor); } investorEditor.ReadControls(newInvestor); if (InvestorAdded != null) InvestorAdded(this, new EntityEventArgs(newInvestor)); } else if (e.CommandName == "delete") { Investor targetInvestor = DataSource.Where(i => i.Id == Convert.ToInt32(e.CommandArgument)).FirstOrDefault(); if (InvestorDeleted != null) InvestorDeleted(this, new EntityEventArgs(targetInvestor)); } } }I Tried with both the Repeater Item Command and each LinkButton Event to see if it would make any difference, but none worked
Any help would be appreciated
Thanks
Repeater Control DataBind DataBinding
Bigtrend
Contributor
2551 Points
436 Posts
Re: Repeater DataBind not updating Items in Datasource
Jan 28, 2010 03:26 PM|LINK
It is not obvious why DataBind of the Repeater should be called after PostBack - this part of the code is missed within your quotes - could you please either provide it for us or ensure that you don't have something like "if (!IsPostBack) userControl.DataBind();".
fireout
Member
12 Points
8 Posts
Re: Repeater DataBind not updating Items in Datasource
Jan 28, 2010 03:32 PM|LINK
Right, sorry I Haven't include the page itself. Here it is:
public partial class InvestorEditor : Page { protected void Page_Load(object sender, EventArgs e) { if (CurrentInvestorGroup.OwnerInvestor == null) { CurrentInvestorGroup.OwnerInvestor = Entities.Investor.Create<Entities.Investor>(); CurrentInvestorGroup.Investors.Add(CurrentInvestorGroup.OwnerInvestor); } if (!IsPostBack) { investorEditor.Investor = CurrentInvestorGroup.OwnerInvestor; investorList.DataSource = CurrentInvestorGroup.OwnerInvestor.RelatedInvestors.Cast<Entities.Investor>().ToList(); investorList.RootInvestor = CurrentInvestorGroup.OwnerInvestor; investorList.InvestorAdded += investorList_InvestorAdded; investorList.InvestorDeleted += investorList_InvestorDeleted; investorList.DataBind(); } } void investorList_InvestorDeleted(object sender, EntityEventArgs e) { CurrentInvestorGroup.Investors.Remove((Entities.Investor)e.Entity); CurrentInvestorGroup.OwnerInvestor.RelatedInvestors.Remove((Entities.Investor)e.Entity); investorList.DataSource = CurrentInvestorGroup.OwnerInvestor.RelatedInvestors.Cast<Entities.Investor>().ToList(); investorList.DataBind(); } protected void investorList_InvestorAdded(object sender, EntityEventArgs e) { CurrentInvestorGroup.Investors.Add((Entities.Investor)e.Entity); CurrentInvestorGroup.OwnerInvestor.RelatedInvestors.Add((RelatedInvestor)e.Entity); investorList.DataSource = CurrentInvestorGroup.OwnerInvestor.RelatedInvestors.Cast<Entities.Investor>().ToList(); investorList.DataBind(); } }The usercontrol (investorList) is included in the markup within the page directrlky (not within repeater or any other templated control)
fireout
Member
12 Points
8 Posts
Re: Repeater DataBind not updating Items in Datasource
Jan 28, 2010 03:56 PM|LINK
I haven't figured it out yet but I found something wierd.
If i watch the IsPostBack Property, when I step through the code on my usercontrol (on an actual postback) it is set to true.
Once my usercontrol code calls the event delegate, the method on my page hooked to this event fires and within this method, the IsPostBack property is false.
So it looks like the method on my page are called within another scope or something...?!
Bigtrend
Contributor
2551 Points
436 Posts
Re: Repeater DataBind not updating Items in Datasource
Jan 28, 2010 06:13 PM|LINK
I don't see why the item should be deleted? What is the storage you are using for management of your data?
Are you sure that the item you see is indeed deleted from this storage?
From the code above it doesn't matter what the value of IsPostBack is during the code execution because it will invoke the DataBind for the same source (within Page_Load and InvestorDeleted event handlers).
fireout
Member
12 Points
8 Posts
Re: Repeater DataBind not updating Items in Datasource
Jan 28, 2010 06:34 PM|LINK
I figured out what the problem is but I still can't understand why.
My solution is to use the sender (within the InvestorDeleted handler) instead of the investirList. Seems that, in that sequence, the page's investorList control is not the same instance as the sender.
protected void investorList_InvestorDeleted(object sender, EntityEventArgs e) { CurrentInvestorGroup.Investors.Remove((Entities.Investor)e.Entity); CurrentInvestorGroup.OwnerInvestor.RelatedInvestors.Remove((Entities.Investor)e.Entity); ((InvestorList)sender).DataSource = CurrentInvestorGroup.OwnerInvestor.RelatedInvestors.Cast<Entities.Investor>().ToList(); //investorList.DataBind(); }and then DataBind within the UserControl event handler
Does that mean also for the same instance? (ie: for the instance of the page created on the original get (when the handler was assigned))
Because that would explain why it isn't the same instance of the usercontrol, but isn't it supposed to be the instance of the current request (post)?
Thanks
Bigtrend
Contributor
2551 Points
436 Posts
Re: Repeater DataBind not updating Items in Datasource
Jan 28, 2010 06:50 PM|LINK
I am wondering why do you have the troubles with binding because it seems that for any binding within your code the same data source is used - thus in case the entry is indeed deleted you can't see after any DataBind execution (it doesn't matter for which instance you executed it).
Question which I still have - do you use SQL server for storage the data? Did you check that the entry is deleted from the database? Did you check that the object which you are using for DataBind (everywhere as I see!) is indeed updated with the entry deleting change?
fireout
Member
12 Points
8 Posts
Re: Repeater DataBind not updating Items in Datasource
Jan 28, 2010 07:00 PM|LINK
In this flow, the data is only stored on the SessionState. the data is persisted on a SaveButton_Click (on my master page)
But I figured out what happens... On my usercontrol, i when I was saving my control state, i was saving the handler registered along with it. So when I was reloading my state (on postback) i was reassigning the event handler of the Get instance of my page.
So then, within my handler, when I was setting the DataSource or Databinding my list, it would set it to the instance of my Get, databinding the list on the same instance, but the Instance of my page for the Post was staying untouched.
The data on the SessionState was updated, it was only the repeater that wouldn't bind on my updated version (it actually didn't rebind at all since It was binding the previous page's (get) repeater)
Thanks for your help!
The point of the story is, never keep handlers on any controlstate