C # /. NET 2.0: Problem with Repeater controller and checkboxes inside a custom control!
I have a relay control with a checkbox, if I check the checkbox then my delete function will delete the item in the base table.
When I test the delete function on the aspx page with code by page everything works fine. Hooray!
However, when I take a repeater and put it in User Control, the delete function thinks that my repeater controller has no items.
Code as below, I tried to exclude unnecessary code. I asked this question on the asp.net forums but no one answered!
asxc:
<%@ Control AutoEventWireup="true" Inherits="Moto.Web.UI.UserControls.Messages.MessageListForm" Language="C#" %>
<asp:button id="btnDelete" runat="server" text="Delete" OnClick="btnDelete_Click" ></asp:button>
<asp:Repeater ID="RepeaterMessageList" runat="server" EnableViewState="true" >
<ItemTemplate >
<div class="messageContainer item" >
<div class="messageListLeft">
<div class="messageList">
<asp:Image ID="imgUser" runat="server" CssClass="" />
<asp:CheckBox ID="chkDeleteMe" runat="server" Text="test" />
</div>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
File code:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections;
using System.Collections.Generic;
using System.IO;
namespace Moto.Web.UI.UserControls.Messages
{
public class MessageListForm : Moto.Web.UI.UserControls.UserControl//System.Web.UI.UserControl
{
private string userGUID;
private MembershipUser MembershipUser;
private Moto.Business.UserComponent userComponent;
private Moto.Business.User user;
private Button cmdPrev;
private Button cmdNext;
private Button cmdNewest;
private Button cmdOldest;
private Label lblCurrentPage;
private Label lblMessage;
private HyperLink hypPageRedirect;
private Repeater RepeaterMessageList;
private MessageView DisplayMessages = MessageView.Inbox;//default setting
private Button btnDelete;
private Label lblConfirmDelete;
protected Button btnConfirmDelete;
protected Button btnCancelDelete;
enum MessageView
{
Inbox, //0
Sent //1
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.InitializePage();
}
protected void InitializePage()
{
this.cmdNext = (Button)FindControl("cmdNext");
this.cmdPrev = (Button)FindControl("cmdPrev");
this.cmdOldest = (Button)FindControl("cmdOldest");
this.cmdNewest = (Button)FindControl("cmdNewest");
this.lblCurrentPage = (Label)FindControl("lblCurrentPage");
// this.RepeaterMessageList = (Repeater)FindControl("RepeaterMessageList");
this.RepeaterMessageList = (Repeater)FindControlRecursive(this, "RepeaterMessageList");
this.hypPageRedirect = (HyperLink)FindControl("hypPageRedirect");
this.lblMessage = (Label)FindControl("lblMessage");
//delete functionality
this.btnDelete = (Button)FindControl("btnDelete");
this.lblConfirmDelete = (Label)FindControl("lblConfirmDelete");
this.btnConfirmDelete = (Button)FindControl("btnConfirmDelete");
this.btnCancelDelete = (Button)FindControl("btnCancelDelete");
//where are we coming from - are we the Logged in user or just a voyeur?
if (Page.User.Identity.IsAuthenticated)
{
this.userComponent = new Moto.Business.UserComponent();
this.MembershipUser = Membership.GetUser();//user logged in
this.userGUID = this.MembershipUser.ProviderUserKey.ToString();//signed in user
this.user = this.userComponent.GetByUserGUID(this.userGUID);
}
else
{
Response.Redirect("~/default.aspx");
}
if (null != this.Page.Request.QueryString["viewing"])
{
//reset the enum value
DisplayMessages = this.Page.Request.QueryString["viewing"].ToLower() == "sent" ? MessageView.Sent : MessageView.Inbox;
CurrentPage = 0;//if it a redirect then reset the Current Page
}
}
void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ItemsGet();//on post back we'll call it elsewhere
}
switch (DisplayMessages)
{
case MessageView.Sent:
this.hypPageRedirect.Text += "Inbox";
this.hypPageRedirect.NavigateUrl += "?viewing=Inbox";
break;
case MessageView.Inbox:
this.hypPageRedirect.Text += "Sent Items";
this.hypPageRedirect.NavigateUrl += "?viewing=Sent";
break;
}
}
protected void cmdPrev_Click(object sender, EventArgs e)
{
// Set viewstate variable to the previous page
CurrentPage -= 1;
// Reload control
ItemsGet();
}
protected void cmdNext_Click(object sender, EventArgs e)
{
// Set viewstate variable to the next page
CurrentPage += 1;
// Reload control
ItemsGet();
}
protected void cmdNewest_Click(object sender, EventArgs e)
{
// Set viewstate variable to the previous page
CurrentPage = 0;
// Reload control
ItemsGet();
}
protected void cmdOldest_Click(object sender, EventArgs e)
{
}
public void RepeaterMessageList_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// Execute the following logic for Items and Alternating Items.
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
//Are we vieing the Inbox or Sent items?
if (DisplayMessages == MessageView.Inbox)
{
.........Do stuff
}
else
{
.........Do stuff
}
}
}
private void ItemsGet()
{
// this.RepeaterMessageList = (Repeater)FindControl("RepeaterMessageList");
this.RepeaterMessageList.ItemDataBound += new RepeaterItemEventHandler(RepeaterMessageList_ItemDataBound);
// Populate the repeater control with the Items DataSet
PagedDataSource objPds = new PagedDataSource();
if (DisplayMessages == MessageView.Inbox)//which table are we getting data from?
{
List<Moto.Business.MessageReceived> messages;
Moto.Business.MessageReceivedComponent messageComponent =
new Moto.Business.MessageReceivedComponent();
messages = messageComponent.GetByReceiverGUID(this.user.UserGUID);
objPds.DataSource = messages;
}
else
{
List<Moto.Business.MessageSent> messages;
Moto.Business.MessageSentComponent messageComponent =
new Moto.Business.MessageSentComponent();
messages = messageComponent.GetBySenderGUID(this.user.UserGUID);
objPds.DataSource = messages; //Items.Tables[0].DefaultView;
}
// Indicate that the data should be paged
objPds.AllowPaging = true;
// Set the number of items you wish to display per page
objPds.PageSize = 25;
// Set the PagedDataSource current page
objPds.CurrentPageIndex = CurrentPage;
this.lblCurrentPage.Text = "Page " + (CurrentPage + 1).ToString() + " of "
+ objPds.PageCount.ToString();
// Disable Prev or Next buttons if necessary
this.cmdPrev.Enabled = !objPds.IsFirstPage;
this.cmdNext.Enabled = !objPds.IsLastPage;
this.cmdOldest.Enabled = !objPds.IsLastPage;
this.cmdNewest.Enabled = !objPds.IsFirstPage;
this.RepeaterMessageList.DataSource = objPds;
this.RepeaterMessageList.DataBind();
}
public int CurrentPage
{
get
{
// look for current page in ViewState
object o = this.ViewState["_messagesCurrentPage"];
if (o == null)
return 0; // default page index of 0
else
return (int)o;
}
set
{
this.ViewState["_messagesCurrentPage"] = value;
}
}
protected void btnDelete_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in this.RepeaterMessageList.Items)
{
CheckBox chkDeleteMe = item.FindControl("chkDeleteMe") as CheckBox;
TextBox test = item.FindControl("test") as TextBox;
if (chkDeleteMe.Checked)
{
if (DisplayMessages == MessageView.Inbox)//which table are we getting data from?
{
.........Do stuff
}
else
{
.........Do stuff
}
}
}
// Reload control
ItemsGet();
}
protected Control FindControlRecursive(Control root, string id)
{
if (root.ID == id)
{
return root;
}
foreach (Control c in root.Controls)
{
Control t = FindControlRecursive(c, id);
if (t != null)
{
return t;
}
}
return null;
}
}
Any help is greatly appreciated!
I think the problem is that when the Delete button is clicked, the Page_Load is fired again, and after posting it back, it doesn't execute the ItemsGet method and hence the relay has no data.
Try putting your ItemsGet method call in the OnPreRender event instead of Page_Load.
Jomit
source to share
So it binds to the relay and displays all the items correctly, but nothing was found when re-viewing the list of items by post back?
Is the delete event definitely fired? What is visible after clicking the delete button? (for example this table is empty or still displays all items)
Update:
Comment out the GetItems method and see if the table is empty or not on postback. It looks like your viewstate relays are no longer populating the control or whatever.
source to share
PreRender's solution also worked in our case, where we had code like this on two pages of our application. This worked fine in .Net 1.1, but however it broke when we ported this code to .Net 2.0.
Not sure why it broke without any major changes to the codebase.
Thanks for the OnPreRender tip!
-Ghanshyam