データ ソース コントロールは、Microsoft Visual Studio 2005 で導入された新しいタイプのサーバー コントロールです。データ ソース コントロールはデータ バインディング アーキテクチャの重要な部分であり、データ バインディング コントロールを通じて宣言型プログラミング モデルと自動データ バインディング動作を提供できます。この記事とこのシリーズの後続の記事では、データ ソース コントロールの実装の中核となる要素を紹介します。
はじめにつまり
、データ ソース コントロールは、データ ストアと、含まれるデータに対して実行できるいくつかの操作を要約したものです。 DataBound コントロールは、DataSourceID プロパティを通じてデータ ソース コントロールに関連付けられます。従来のデータ ストアのほとんどは表形式または階層形式であり、データ ソース コントロールはそれに応じて分割されます。ここで紹介するのは、表形式のデータ ソース コントロールです。
データ ソース コントロール自体はあまり機能しません。すべてのロジックは DataSourceView 派生クラスにカプセル化されます。少なくとも 1 つの DataSourceView は、行のセットを取得する (つまり、SELECT する) 機能を実装する必要があります。データを変更する機能 (つまり、INSERT、UPDATE、DELETE) を提供できます (オプション)。データ バインドされたコントロールは、さまざまな Can??? プロパティを通じて有効な機能セットを確認できます。データ ソース コントロール自体は、1 つ以上の一意の名前が付けられたビューのコンテナーにすぎません。慣例により、デフォルトのビューには名前でアクセスすることも、空にすることもできます。異なるビュー間に存在するかどうか、またはどのような関係が存在するかは、各データ ソース コントロールの実装に基づいて適切に定義できます。たとえば、データ ソース コントロールは、異なるビューを通じて同じデータの異なるフィルター処理されたビューを提供したり、セカンダリ ビューで一連の下位行を提供したりする場合があります。データ バインド コントロールの DataMember プロパティを使用して、特定のビューを選択できます (データ ソース コントロールが複数のビューを提供する場合)。現在、Whidbey の組み込みデータ ソース コントロールでは複数のビューが提供されていないことに注意してください。
最後に内容をいくつかご紹介します。データ ソース コントロール (およびそのビュー) は 2 セットの API を実装します。 API の最初のセットは、データ バインドされたコントロールから通常の方法で使用できる 4 つの一般的なデータ操作用に定義された抽象インターフェイスです。 2 番目のグループはオプションで、それが表すドメインまたはデータ ストアに関して定義され、通常は厳密に型指定され、アプリケーション開発者を対象としています。
例
これらの記事では、weather.com (英語) が提供する REST (英語) XML API に対して動作し、郵便番号に基づいて気象情報を取得する WeatherDataSource を実装します。通常、派生データ ソース コントロールが最初に実装されます。
パブリック クラス WeatherDataSource : DataSourceControl {
パブリック静的読み取り専用文字列
CurrentConditionsViewName = "CurrentConditions";
WeatherDataSourceView
_currentConditionsView;
得る {
if (_currentConditionsView == null) {
_currentConditionsView = 新しい WeatherDataSourceView(this, CurrentConditionsViewName);
}
_currentConditionsView を返す;
}
文字
列郵便番号 {
得る {
文字列 s = (文字列)ViewState["ZipCode"];
return (s != null) s : String.Empty;
}
セット {
if (String.Compare(値, 郵便番号,
StringComparison.Ordinal) != 0) {
ViewState["ZipCode"] = 値;
CurrentConditionsView.RaiseChangedEvent();
}
}
protected オーバーライド DataSourceView GetView(string viewName)
{
if (String.IsNullOrEmpty(viewName) ||
(String.Compare(viewName, CurrentConditionsViewName,
StringComparison.OrdinalIgnoreCase) == 0)) {
CurrentConditionsView を返します。
}
throw new ArgumentOutOfRangeException("viewName");
protected オーバーライド ICollection GetViewNames()
{
新しい文字列を返します[] { CurrentConditionsViewName };
パブリック天気 GetWeather()
{
CurrentConditionView.GetWeather() を返します。
}
ご覧のとおり、基本的な考え方は、名前付きビュー インスタンスを返すために GetView を実装し、利用可能なビューのセットを返すために GetViewNames を実装することです
。
ここでは「DataSourceControl から派生」を選択します。気づきにくい点の 1 つは、データ バインド コントロールが実際に IDataSource インターフェイスを検索し、DataSource コントロールが GetView と GetViewNames を実装することによってインターフェイスを実装していることです。インターフェイスが必要な理由は、データ ソース コントロールを表形式と階層の両方にできるようにするためです (可能であれば、その場合はメイン モデルから派生し、別のモデルをインターフェイスとして実装します)。次に、さまざまなシナリオで他のコントロールを変換して、データ ソースの容量を 2 倍にすることもできます。 また、パブリック ZipCode プロパティと、厳密に型指定された Weather オブジェクトを返す GetWeather メソッドにも注目してください。この API はページ開発者に適しています。ページ開発者は、DataSourceControl と DataSourceView について考える必要はありません。
次のステップは、データ ソース ビュー自体を実装することです。この特定の例では、SELECT レベルの機能のみが提供されます (これが最小要件であり、このシナリオで役立つ唯一の機能です)。
プライベート シールド クラス WeatherDataSourceView : DataSourceView {
private WeatherDataSource _owner;
public WeatherDataSourceView(WeatherDataSource owner, string viewName)
:base(owner, viewName) {
_owner = 所有者;
protected
オーバーライド IEnumerable ExecuteSelect(
DataSourceSelectArguments 引数) {
argument.RaiseUnsupportedCapabilitiesError(this);
天気 WeatherObject = GetWeather();
新しい Weather[] { WeatherObject } を返します。
内部天気 GetWeather()
{
文字列 zipCode = _owner.ZipCode;
if (zipCode.Length == 0) {
新しい InvalidOperationException() をスローします。
WeatherService
WeatherService = new WeatherService(zipCode);
戻りweatherService.GetWeather();
内部 void RaiseChangedEvent()
{
OnDataSourceViewChanged(EventArgs.Empty);
}
デフォルト
では、DataSourceView クラスは CanUpdate などのプロパティから false を返し、Update および関連メソッドから NotSupportedException をスローします。ここで WeatherDataSourceView で行う必要があるのは、抽象 ExecuteSelect メソッドをオーバーライドし、「選択された」気象データを含む IEnumerable を返すことだけです。実装では、ヘルパー WeatherService クラスが使用されます。このクラスは、単に WebRequest オブジェクトを使用して、選択した郵便番号を使用して Weather.com (英語) をクエリします (これについては特別なことは何もありません)。
ExecuteSelect が保護済みとしてマークされていることにお気づきかもしれません。データ バインド コントロールが実際に呼び出すのは、コールバックで渡されるパブリック (およびシールされた) Select メソッドです。 Select の実装は ExecuteSelect を呼び出し、結果として得られる IEnumerable インスタンスを使用してコールバックを呼び出します。このパターンは非常に奇妙です。これには理由があります。これについては、このシリーズの後続の記事で説明します。お待ちください...
この使用例を次に示します。
郵便番号: <asp:TextBox runat="server" id="zipCodeTextBox" />
<asp:Button runat="server" onclick="OnLookupButtonClick" Text="Look" />
<hr />
<asp:FormView runat="server" DataSourceID="weatherDS">
<アイテムテンプレート>
<asp:Label runat="サーバー"
Text='<%# Eval("温度", "現在の温度は {0} です。") %>' />
</アイテムテンプレート>
</asp:FormView>
<nk:WeatherDataSource runat="server" id="weatherDS" ZipCode="98052" />
<script runat="server">
private void OnLookupButtonClick(オブジェクト送信者, EventArgs e) {
WeatherDS.ZipCode = zipCodeTextBox.Text.Trim();
}
、
ユーザー入力に応じて郵便番号を設定します。これにより、データ ソースが変更通知を発行し、バインドされた FormView コントロールがデータ バインディングを実行して表示を変更します。
これで、データ アクセス コードがデータ ソース コントロールにカプセル化されました。さらに、このモデルにより、weather.com (英語) は、サービス固有の詳細もカプセル化できるコンポーネントを公開できるようになります。うまくいけばいいですね。さらに、抽象データ ソース インターフェイスにより、FormView は気象データのみを操作できます。
次の記事では、データのクエリに使用されるフィルター値 (郵便番号) の変更を自動的に処理できるようにデータ ソース コントロールを拡張します。