top
Loading...
ASP.NET2.0中使用數據源控件之參數
數據源控件需要使用參數值來指定需要選擇哪些數據,或者指定如何修改數據以及修改什么數據。通常情況下,頁面包含一些 UI,以定義那些必須在選擇操作中使用的參數,而數據綁定控件提供了參數值來進行插入、更新和刪除操作。但是,在任意一種情況下,都可能同時出現兩種現象。在第 1 部分中,數據源控件揭示了 ZipCode 屬性,該屬性可進行聲明性設置,或者以編碼來設置以響應用戶操作。參數被設計為以聲明性(且可擴展)的方式來完成此方案。

引言

Parameter 基類代表一個通用參數。Microsoft Visual Studio 2005 提供了諸如 QueryStringParameter 之類的參數,以便將數據從查詢字符串參數請求到數據源中。另一個非常有用的參數是 ControlParameter,該參數允許從任一控件屬性中請求數據。如果內置參數類型不能滿足您的要求,則您可以定義自己的參數類型。這樣您就可以使頁面與粘接代碼不相關,而是將該代碼整齊地封裝在參數實現中。

除了從不同的源中請求值,這些參數還可以跟蹤值的更改情況,并通知這些更改的所屬數據源,進而引發數據源更改通知,最終在數據綁定控件中觸發數據綁定操作。簡而言之,這就是使用 ControlParameters 時,主要的聲明性詳細方案所依據的原理。

示例

在此將向 WeatherDataSource 添加參數功能,然后進一步闡述。

public class WeatherDataSource : DataSourceControl {

public static readonly string ZipCodeParameterName = "ZipCode";
...

private ParameterCollection _parameters;

private ParameterCollection Parameters {
get {
if (_parameters == null) {
_parameters = new ParameterCollection();
_parameters.ParametersChanged += new EventHandler(this.OnParametersChanged);
if (IsTrackingViewState) {
((IStateManager)_parameters).TrackViewState();
}
}
return _parameters;
}
}
...

public string GetSelectedZipCode() {
if (_parameters != null) {
Parameter zipCodeParameter = _parameters[ZipCodeParameterName];
if (zipCodeParameter != null) {
IOrderedDictionary parameterValues = _parameters.GetValues(Context, this);
return (string)parameterValues[zipCodeParameter.Name];
}
}

return ZipCode;
}

protected override void LoadViewState(object state) {
object baseState = null;

if (state != null) {
Pair p = (Pair)state;
baseState = p.First;

if (p.Second != null) {
((IStateManager)Parameters).LoadViewState(p.Second);
}
}
base.LoadViewState(baseState);
}

protected override void OnInit(EventArgs e) {
Page.LoadComplete += new EventHandler(this.OnPageLoadComplete);
}

private void OnPageLoadComplete(object sender, EventArgs e) {
if (_parameters != null) {
_parameters.UpdateValues(Context, this);
}
}

private void OnParametersChanged(object sender, EventArgs e) {
CurrentConditionsView.RaiseChangedEvent();
}

protected override object SaveViewState() {
object baseState = base.SaveViewState();
object parameterState = null;

if (_parameters != null) {
parameterState = ((IStateManager)_parameters).SaveViewState();
}

if ((baseState != null) || (parameterState != null)) {
return new Pair(baseState, parameterState);
}
return null;
}

protected override void TrackViewState() {
base.TrackViewState();
if (_parameters != null) {
((IStateManager)_parameters).TrackViewState();
}
}
}

Microsoft ASP.NET 提供了 ParameterCollection,您可以完全按原樣使用該集合。它同時包含更改跟蹤和狀態管理功能。您只需相應地調用該集合的 API 來合并這些功能,另外還可以在控件外將該集合揭示為屬性。在上述代碼中,需要注意的關鍵點為:

·該數據源控件揭示了一個 ParameterCollection 類型的屬性,以使開發人員能夠添加表示要使用的郵政編碼值的參數。如果已經設置了參數,則使用該參數;否則,將使用 ZipCode 屬性值。

·該控件替代了與狀態管理相關的方法,以請求 ParameterCollection 中內置的狀態管理功能。

·該控件使用頁面生命周期的新 LoadComplete 事件來更新參數值,它通過替代 OnInit 來注冊這些值。如果在初始化、回發處理或頁面編碼(當引發 LoadComplete 時,全部都會發生)期間更改了任何參數的值,則該數據源控件還會注冊 ParameterCollection 所引發的 ParametersChanged 事件。與上述情況一樣,如果設置了 ZipCode 屬性,將會引發更改通知,向數據綁定控件指明它需要再次執行數據綁定操作(隨后在 PreRender 期間將會發生此情況)。

·需要參與生命周期是數據源作為控件(即使是非可視控件)來實現的一個原因。另一個原因是為了使數據綁定控件能夠通過使用其 DataSourceID 屬性來使用 FindControl,并能夠獲得基于 INamingContainer 的分層名稱領域的益處(這樣就能夠實現嵌套數據方案,方法是在模板內放置一個數據源控件,并使其在每行中重復一次)。數據源是控件這一事實早已是爭論的焦點 - 但愿這能夠說明此問題的一些論據。

在此 DataSourceView 只需調用 GetSelectedZipCode,而不是直接使用 ZipCode 屬性。此外,還更改了數據源視圖代碼,以便在未選中 ZipCode 的情況下返回 null(而不是拋出異常),這會導致數據綁定控件顯示“空”視圖。這在通常情況下是一個慣例,但是回顧來看,這應該成為數據源控件語義的一個不可獲缺的方面。

private sealed class WeatherDataSourceView : DataSourceView {
...

internal Weather GetWeather() {
string zipCode = _owner.GetSelectedZipCode();
if (zipCode.Length == 0) {
return null;
}

WeatherService weatherService = new WeatherService(zipCode);
return weatherService.GetWeather();
}
}

完整的代碼就是這個樣子。以下是經過更新的用法示例,該示例現在是聲明性的。

Zip Code: <asp:TextBox runat="server" id="zipCodeTextBox" />
<asp:Button runat="server" Text="查找" />
<hr />

<asp:FormView runat="server" DataSourceID="weatherDS">
<ItemTemplate>
<asp:Label runat="server"
Text='<%# Eval("Temperature",
"當前溫度是 {0}。") %>' />
</ItemTemplate>
</asp:FormView>
<nk:WeatherDataSource runat="server" id="weatherDS">
<Parameters>
<asp:ControlParameter Name="ZipCode" ControlID="zipCodeTextBox" />
</Parameters>
</nk:WeatherDataSource>

請注意,在標記中并未指定 Text 作為在 ControlParameter 標記上查找的屬性。ControlParameter 自動計算出了在未指定屬性的情況下要使用的默認屬性。它通過檢查該類中的 ControlValueAttribute 來實現此目的。TextBox 將 Text 定義為包含其“控件值”的屬性。除了傳統輸入控件之外,此概念還適用于多個控件。例如,GridView 將其 SelectedDataKey 揭示為“控件值”。這是一個新事物,控件開發人員從此以后應該予以考慮,以便與 ControlParameter 更好地進行集成。


作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗