Here is how I apply the principle. In my work project, I encounter a problem to paginate a GridView which is inside a data control. I am keep getting error message saying ""Object reference not set to an instance of an object.".
Reproduce the problem
So I start out to create the problem with minimal amount of code. The following code shows a repeater control and within the repeater control it display a GridView control which has pagination enabled. Upon page loading, it sets the datasource for the repeater and call the DataBind() method to update the repeater and its child controls. It works fine on the first initial page load, but fails when you click on the numbers that represents each page of the GridView.
<asp :Repeater ID="Repeater1" runat="server">
<ItemTemplate>
< asp:GridView ID="GridView1" runat ="server" AllowPaging="True" EnableSortingAndPagingCallbacks ="True"
PageSize="2" DataSource=' <%# ( (A) Container.DataItem).b %> '>
</asp:GridView >
</ItemTemplate>
</ asp:Repeater>
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
A a = new A();
a.b = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Repeater1.DataSource = new List<A>(new A[] {a});
Repeater1.DataBind ();
}
}
Tackle the problem
A quick search on the e-books that I have and on the Internet could not find any information on the topic. One related the article shows a technique to display GridView within a GridView is the closest that I can find. It uses 2 datasource controls and bind the child datasource at runtime. In the problem code above, I bind the datasource declaratively. Maybe declaration of child datasource only takes effect via the page loading not the subsequent page post-back. That is exactly how my test code fails.
So I quickly change the code as the following: (changes are in bold)
< asp:Repeater ID="Repeater1" runat ="server" OnItemDataBound ="Repeater1_ItemDataBound">
<ItemTemplate>
<asp:GridView ID="GridView1" runat="server" AllowPaging ="True" EnableSortingAndPagingCallbacks="True"
PageSize="2" OnDataBinding="GridView1_DataBinding" >
</asp:GridView>
</ItemTemplate>
</asp:Repeater>
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
GridView gv = ( GridView) e.Item. FindControl("GridView1");
gv.DataBind();
}
protected void GridView1_DataBinding(object sender, EventArgs e)
{
GridView gv = ( GridView)sender;
gv.DataSource = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
}
Basically, I removed the declarative databinding for the GridView and intercept 2 events that will allow me to populate the GridView programmatically. The chain of events that fires are Repeater1_Databinding, Repeater1_itemDataBound, Gridview1_DataBinding. The last 2 events will repeat as many times as the amount of data in the repeater.
Now we have a solution and just need to port it to my work project.
No comments:
Post a Comment