LinkButton and User Control Error
I have a user control, which consists of a gridview and link button. The problem being, the link button won't work! Can someone please have a look and show me why and how to solve it please!
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var model = new List<UserControlProof.Model.Customer> {
new UserControlProof.Model.Customer {
Name = "Customer1", address = "Addr1" }),
new UserControlProof.Model.Customer {
Name = "Customer2", address = "Addr1" }),
new UserControlProof.Model.Customer {
Name = "Customer3", address = "Addr2" }),
new UserControlProof.Model.Customer {
Name = "Customer4", address = "Addr3" }) };
var Addr = (from m in model select m.address).Distinct();
foreach (string addr in Addr)
{
var cr = (UserControlProof.Controls.CollapseableRecordset)LoadControl(
"Controls//CollapseableRecordset.ascx");
cr.ID = cr.UniqueID;
form1.Controls.Add(cr);
cr.DisplayName = Addr;
var filterredAddress = from m in model where m.address == addr select m;
cr.DataSource = filterredAddress;
cr.Count = filterredAddress.Count();
if (cr.Count == 1)
{
cr.ViewCustomers = true;
}
cr.DataBind();
form1.Controls.Add(new Literal() { Text = "<br />" });
}
}
}
public partial class CollapseableRecordset : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridView1.Columns.Clear();
BoundField f1 = new BoundField();
f1.DataField = "Customer";
f1.ShowHeader = false;
GridView1.Columns.Add(f1);
}
}
//private string displayName;
public string DisplayName
{
get
{
EnsureChildControls();
return LabelName.Text;
//return displayName;
}
set
{
EnsureChildControls();
LabelName.Text = value;
//displayName = value;
}
}
//private int count;
public int Count
{
get
{
EnsureChildControls();
return int.Parse(LabelCount.Text);
//return count;
}
set
{
EnsureChildControls();
LabelCount.Text = value.ToString();
//count = value;
}
}
//private bool ViewCustomers;
public bool ViewCustomers
{
get
{
EnsureChildControls();
return Link1.Visible;
}
set
{
EnsureChildControls();
Link1.Visible = value;
}
}
public object DataSource
{
get
{
EnsureChildControls();
return GridView1.DataSource;
}
set
{
EnsureChildControls();
GridView1.DataSource = value;
}
}
protected void Link1_Click(object s开发者_C百科ender, EventArgs e)
{
Label1.Visible = true;
}
}
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="CollapseableRecordset.ascx.cs" Inherits="UserControlProof.Controls.CollapseableRecordset" %>
<%@ Register Assembly="Microsoft.Practices.Web.UI.WebControls" Namespace="Microsoft.Practices.Web.UI.WebControls"
TagPrefix="pp" %>
<asp:Label ID="LabelName" runat="server" Text="Name"></asp:Label>
<asp:Label ID="LabelCount" runat="server" Text="Count"></asp:Label>
<asp:Panel ID="Panel1" runat="server">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
ShowHeader="False">
</asp:GridView>
<br />
<asp:Label ID="Label1" runat="server" Text="Label" Visible="false"></asp:Label>
</asp:Panel>
<asp:LinkButton ID="Link1" runat="server" Text="View All"></asp:LinkButton>
public class Customer
{
public string Name { get; set; }
public string address { get; set; }
}
You're missing setting up the event handler in your LinkButton
. Your button markup should look more like this:
<asp:LinkButton ID="Link1" runat="server" Text="View All" OnClick="Link1_Click"/>
Response to follow-up question:
Dynamically-added event handlers do not "survive" the ASP.NET page life cycle. Getting acquainted with this life cycle will help you out immensely in understanding web forms programming. See this document for a good overview.
The reason why the event handler stops working when not declared is that the HTML page generated by ASP.NET does not contain any information about server-side binding; that is all set up during the post-back. ASP.NET sees a posted form, inspects the items in the post data, then populates your server-side objects and calls event handlers based on the page definition. Since your page definition doesn't contain the LinkButton
, it is unable to know to call your event handler.
In short, ASP.NET web forms tries to set up the illusion of a unified, stateful, client-to-server form, but the illusion is easily shattered when trying to do things outside of the usual pattern. You can work around these limitations, but you'll make things much easier on yourself if you just declare your controls in markup.
Here's how you could work around the link button issue. In your form's Load
event, look at the data in the Request.Form
collection to see if lnkShowAllCust
was the cause of your postback. If it was, call your method for handling the click. This is essentially what the web forms framework does for you:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
string eventSource = Request.Form["__EVENTTARGET"];
if (eventSource != null && eventSource.EndsWith("lnkShowAllCust"))
{
Link1_Click(null, EventArgs.Empty);
}
}
}
Where's your Click
event handler for the LinkButton
. I see the
protected void Link1_Click(object sender, EventArgs e)
{
Label1.Visible = true;
}
method which I'm assuming is supposed to be executed when Link1 is clicked but I don't see how you bind the event.
As far as I understood in your CollapseableRecordset you create a boundfield and map it to Customer datafield
f1.DataField = "Customer";
but you bind the customer list to your control (it's gridview) so the dataitem is "Customer" but properties you bind to are "Name" and "address" if you use for example "Name" field or
f1.DataField = "Name";
you'll get a list of customer names
I have added to the click event to the control, and yes this works. However, in my proof of concept, I added a control dynamically, and this control wouldn't work, and in the markup I have added the link button with a click event.
Here's my code:
public partial class ucCustomerDetails : System.Web.UI.UserControl
{
protected override void CreateChildControls( )
{
base.CreateChildControls( );
this.lnkShowAllCust.ID = "lnkShowAllCust";
this.lnkShowAllCust.Click += new EventHandler(this.lnkShowAllCust_Click);
this.Controls.Add(lnkShowAllCust);
}
protected override void OnInit (EventArgs e)
{
CreateChildControls( );
base.OnInit(e);
}
protected override void OnLoad(EventArgs e)
{
base.EnsureChildControls( );
}
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
CreateChildControls( );
}
}
protected void lnkShowAllCust_Click(object sender, EventArgs e)
{
this.OnCustShowAllClicked(new EventArgs ( ));
}
protected virtual void OnCustShowAllClicked(EventArgs args)
{
if (this.ViewAllClicked != null)
{
this.ViewAllClicked(this, args);
}
}
public event EventHandler ViewAllClicked;
}
If you read the link provided about Page Events you'll see that you need to create your dynamic controls in an event before Page_Load. Page_Init is pretty much the recommended event for this.
精彩评论