2010
04 28

ListView動態綁定資料來源時的分頁問題

19:36:00   閱讀數 ( 1184 )   回應數 ( 0 )
當我們ListView的資料來源是採用動態綁定的方式時,
在換頁上會遇到需點擊第二次才換到正確頁碼的問題…

讓我們用上篇的Code,稍為修改一下來做測試:
<asp:ListView ID="Main_LV" runat="server" ItemPlaceholderID="PH_Inner">
<LayoutTemplate>
		
	<div style="width:300px;border:gray 1px dotted;margin:2px">
		<ul>
			<asp:PlaceHolder ID="PH_Inner" runat="server" />
		</ul>
	</div>

</LayoutTemplate>
<ItemTemplate>

	<li>
		<%# Eval("Name") %> &nbsp;	
		<small><%# Eval("DateTimeCreate","{0:yyyy-MM-dd}") %></small>
	</li>

</ItemTemplate>
</asp:ListView>

<div style="width:300px;border:blue 1px dotted;margin:2px">
	<asp:DataPager ID="Main_DP" runat="server" PageSize="3" PagedControlID="Main_LV" runat="server">
	<Fields>
		<asp:NumericPagerField />
	</Fields>
	</asp:DataPager>
</div>
在僅有ListView與DataPager情況下,我們在CodeFile中這麼寫:
protected void Page_Load( object sender, EventArgs e )
{
	//讓資料繫結僅在第一次執行
	if( !Page.IsPostBack )
	{
		Main_LV.DataSource = VirtualDAL.GetMembers();
		Main_LV.DataBind();
	}
}
 
你會發現,雖然沒有出錯、可以正常執行,
但是分頁的執行動作,卻要點第二次才會換到正確頁碼


其實我們能從反射WebControl的原始碼得知,當執行換頁動作時,
會觸發DataPager的SetPageProperties事件,而此事件將經由DataPager已連結的控制項,
最終會執行IPageableItemContainer.SetPageProperties函式來達成分頁效果。
(實作IPageableItemContainer的控制項, 目前只有ListView)

簡單的說,我們只要在換頁動作時去觸發DataPager的SetPageProperties事件即可,

那我們就可以在剛剛程式碼加上:
protected void Page_Load( object sender, EventArgs e )
{
	//讓資料繫結僅在第一次執行
	if( !Page.IsPostBack )
	{
		Main_LV.DataSource = VirtualDAL.GetMembers();
		Main_LV.DataBind();
	}

	// 為ListView的PagePropertiesChanging事件
	// 加入一個匿名事件, 目的是執行DataPager的SetPageProperties函式
	// 並且對執行中ListView重新繫結資料
	Main_LV.PagePropertiesChanging += ( obj, arg ) =>
	{
	    Main_DP.SetPageProperties( arg.StartRowIndex, arg.MaximumRows, false );
	    var senderLV = obj as ListView;
	    senderLV.DataSource = VirtualDAL.GetMembers();
	    senderLV.DataBind();
	};
}
我們為ListView的PagePropertiesChanging,加入一個對應的事件,
這邊Random用Lambda來寫,
帶入的參數是obj(ListView)及arg(PagePropertiesChangingEventArgs)
重點就在於SetPageProperties,並且重新做資料繫結。

這樣子在點擊換頁時就可以正確執行囉


一個偷吃步的做法
其實有的時候,你可能並不是在畫面中處理那麼多事務,單純的只是要顯示資料的話,
或許有些人覺得還要替ListView額外寫PagePropertiesChanging事件還蠻麻煩的…

其實有比較簡單的做法,Random一般也用這招,
但因為似乎比較不是正確的做法,所以才叫偷吃步啦

我們知道在.Net的生命週期中,其實一般點擊的事件是在PageLoad之後才執行,

當你點擊DataPager執行分頁動作,其實會觸發自身SetPageProperties,
向ListView設定好頁碼,並且儲存到ViewState中去,
不過這樣就會變成你已經先綁定完資料,才告訴ListView它要換到哪一頁去,
簡單說,如果能在綁定資料之前就告訴ListView正確的頁碼,那就能正確執行了。

那...非常簡單,我們把在 Page_Load 事件中執行的事情,往後移就可以了,

所以我們的Page_Load部份程式碼可以改成:
//把Page_Load事件改為Page_LoadComplete
//protected void Page_Load( object sender, EventArgs e )	
protected void Page_LoadComplete( object sender, EventArgs e )
{
	Main_LV.DataSource = VirtualDAL.GetMembers();
	Main_LV.DataBind();
}

因為我們將資料綁定在Page_LoadComplete才執行,
變成已經觸發完換頁事件,才進行資料綁定到ListView,
所以我們就可以正常的使用DataPager囉,提供給各位參考參考
2010-04-28 19:36:00 By RazgrizHsu       1184 Visits

關於站長 About

RazgrizHsu 的大頭照o.o RazgrizHsu
程式設計之偉大航道
其中的一個小設計師
致力於開發技術研究
願能與各位一同成長!

大家來噗浪 Plurk

免責聲明 Disclaimer

  • 本站所轉載或引用之資料,其版權和知識產權屬於原始所有者。
  • 本站雖力求資料準確,但無法保證或擔保全數資料均準確無誤,許多資料具有時效或環境上的不同,在使用本站資料前應先行初步判斷,若是發現問題,歡迎您通知本站。
  • 在任何情況下,因本站所造成的直接、間接、偶然或其他衍生問題,本站不承擔任何責任。
RandomART程式道-88x31連結用Logo
Copyright © Runart.net 暴走的藝術 since 2009 - 2011
Design By Razgriz Hsu, Asp.net MVC 3 & SqlServer 2008R2.