次の方法で共有


ASP.NET 2.0 用カスタム データ バインド Web サーバー コントロールの開発

更新 : 2007 年 11 月

ASP.NET データ バインド Web サーバー コントロールには、レコードまたはアイテムのコレクションを表すデータ ソースのユーザー インターフェイス (UI: User Interface) があります。データ バインド Web サーバー コントロールの例として、GridView Web サーバー コントロールの概要DataList Web サーバー コントロールの概要Repeater Web サーバー コントロールの概要 が挙げられます。ASP.NET に付属するデータ バインド コントロールの詳細については、「ASP.NET のデータ バインド Web サーバー コントロールの概要」を参照してください。

ASP.NET Version 2.0 では、新しいデータ ソース モデルを使用して、データ バインド コントロールをソース コントロールにバインドできます。そのため、ページング、並べ替え、削除など、データ バインド コントロールとは離れた一般的なデータ操作が可能になります。このモデルは、ページを開発するときに、より柔軟なデータ バインド コントロールを生成し、再利用性のレベルを向上できます。

このトピックでは、カスタムの ASP.NET 2.0 データ バインド サーバー コントロールを実装するために必要な基本手順を説明します。カスタム コントロールの全般的なアーキテクチャや実装方法の詳細については、「ASP.NET カスタム サーバー コントロールの開発」および「チュートリアル : カスタム サーバー コントロールの開発と使用」を参照してください。ASP.NET 1.1 に互換性のあるデータ バインド コントロールを開発する方法の詳細については、「ASP.NET 1.1 用カスタム データ バインド Web サーバー コントロールの開発」および「チュートリアル : ASP.NET 1.1 用カスタム データ バインド ASP.NET Web コントロールの作成」を参照してください。データ ソース コントロールの詳細については、「データ ソース コントロールの概要」を参照してください。

カスタム データ バインド コントロールを作成する場合

カスタム データ バインド コントロールを作成する前に、ASP.NET に付属するデータ バインド コントロールの機能を確認します。既存のコントロールで要件に合う場合や、必要な機能の多くを備えた既存のコントロールを拡張してカスタム コントロールを作成できる場合があります。ASP.NET のデータ バインド コントロールの詳細については、「ASP.NET のデータ バインド Web サーバー コントロールの概要」を参照してください。

カスタム データ バインド コントロールを作成する理由について、いくつか例を挙げて説明します。

  • 既存のデータ バインド コントロールでは使用できない、カスタムの UI、カスタムのデータ並べ替え機能、カスタムのデータ編集機能などが必要な場合。

  • コンパイル済みで再頒布可能なカスタム データ バインド コントロールを作成する場合。

  • ASP.NET に付属するデータ バインド コントロールの機能を拡張する場合。

  • カスタム デザイナで特定の要件に適合するデータ バインド コントロールを作成する場合。

カスタム データ バインド コントロールの基本機能

カスタム データ バインド コントロールは、DataBoundControl クラスや CompositeDataBoundControl クラスなど、データ バインド コントロールの基本クラスの 1 つから派生することで、次のような多数の組み込み機能を自動的に継承します。

  • データ ソースは、IDataSource インターフェイスと、関連する DataSourceView クラスをサポートし、データの名前付きビュー、データ ストアがサポートする操作の種類を問い合わせる機能、オンデマンドのデータ読み込み機能を提供します。

  • データ ソースは、IEnumerable または IListSource の汎用インターフェイスをサポートします。

  • データ バインディング式をサポートします。そのため、ページを開発するときに、公開されているコントロールのマークされたプロパティと、データ ソースとの間にバインディングを作成できます。データ バインド式の詳細については、「データ バインド式の概要」を参照してください。

  • ページのライフ サイクルで、ポストバックごとではなく必要に応じて、データ バインディングのロジックをできるだけ後に呼び出す、自動的なデータ バインディングをサポートします。ページで最初のデータ バインディング要求を実行すると、以降の要求ではビューステートからデータの取得を試みます。これによって、要求ごとにデータ ソースに再接続する必要はなくなるため、パフォーマンスが向上します。

デザイン時に使用できる機能の利用

カスタム データ バインド コントロールを作成するときに、すべての Web サーバー コントロールで使用できるデザイン時の機能があります。カスタム コントロール用のデザイナ クラスとコントロール テンプレートを作成できます。このような機能は、Visual Studio のデザイン ビューなどのビジュアル デザイン サーフェイスで、デザイン時にコントロールを使用する場合に呼び出します。

コントロール デザイナを作成して、ページ開発者がコントロール プロパティをカスタマイズできるデザイン時のインターフェイスを提供することで、デザイン時のカスタム コントロールの使用性を大幅に向上できます。ASP.NET のコントロール デザイナの概要については、「ASP.NET コントロール デザイナの概要」を参照してください。例については、「HierarchicalDataBoundControlDesigner」および「チュートリアル : Web サーバー コントロール用の基本的なコントロール デザイナの作成」を参照してください。

テンプレート コントロールを作成することで、ページ開発者は、コントロールのユーザー インターフェイスを定義するコントロールとマークアップを柔軟に指定できるようになります。カスタム テンプレート コントロールの例については、「テンプレート サーバー コントロールの例」を参照してください。

ASP.NET 2.0 でのカスタム データ バインド コントロールの実装

次の表に、ASP.NET 2.0 でカスタム データ バインド サーバー コントロールを実装する場合に固有の手順をまとめます。表の下に、各実装手順の詳細情報について説明します。

手順

手順の概要

データ バインド コントロールの基本クラスを選択します。

必要な機能の多くを備えている既存のデータ バインド コントロール クラスを拡張するか、基本のデータ バインド コントロール クラスの 1 つから派生します。

データ バインドのプロパティを公開します。

カスタム コントロールを設定し、基本のデータ バインド コントロール クラスが公開する最小限必要なデータ バインド プロパティのほかに、データ バインド プロパティを公開します。

データの取得を開始します。

  • ページ開発者が次の処理を実行してコントロールに割り当てたデータを取得します。

  • 基本のデータ バインド コントロール クラスの PerformSelect メソッドをオーバーライドします。

  • 基本のデータ バインド コントロール クラスの GetData メソッドを呼び出し、コントロールのデータ ソース ビューを取得します。

  • DataSourceView オブジェクトの Select メソッドを呼び出してデータの取得を開始し、データを受け取るコールバック メソッドを指定します。

取得したデータの処理

Select メソッドのパラメータとして指定したコールバック メソッドを指定します。コールバック メソッドには、データを受け取るために、IEnumerable 型の 1 つのパラメータが必要です。コントロールでデータの処理が必要な場合、このコールバック メソッド内で発生します。

データを表す UI オブジェクトの作成

PerformDataBinding メソッドのオーバーライドを指定します。このメソッド内で次のタスクを実行します。

  • PerformDataBinding メソッドを呼び出して、他のコードがこのメソッドに依存して実行できるようにします。

  • データ収集内のデータを列挙し、UI 表示でデータを表現する子コントロールを作成します。

データ バインド コントロールの基本クラスの選択

コントロールを開発するときに、使用できるデータ バインド コントロールの基本クラスの 1 つを拡張してカスタム データ バインド コントロールを作成できます。次の表は、ASP.NET 2.0 で使用できるデータ バインド基本クラスの一覧です。各クラスの説明を確認し、作成するカスタム データ バインド コントロールの要件に最適な基本クラスを決定してください。データ バインド コントロールの各基本クラスの詳細と実装例については、各クラスの説明を参照してください。ASP.NET に付属するデータ バインド コントロールの詳細については、「ASP.NET のデータ バインド Web サーバー コントロールの概要」を参照してください。

クラス

説明

BaseDataBoundControl

  • すべてのデータ バインド コントロールの基本クラスです。すべてのバインド データのデータ バインディングと検証を実行します。

DataBoundControl

標準のデータ バインド コントロールをビルドする基本のデータ バインド クラスです。DataBoundControl は次の処理を実行します。

  • すべてのデータ バインド コントロールが共有する基本実装を提供します。

  • データ ソース コントロールやデータ コンテナと通信するロジックを含めます。

  • TreeViewListControl など、データ バインド コントロールの基本として機能します。

ListControl

  • リスト コントロールの基本クラスです。DataBoundControl クラスを拡張します。Items コレクションと高度なレイアウト描画機能を提供します。

CompositeDataBoundControl

  • DataBoundControl クラスを拡張する基本クラスです。次の機能があります。

  • 複合コントロールに必要な一般的なコードを実装します。ポストバックを作成した後に、ビューステートからコントロールの子コントロールの階層構造を復元するコードなどです。

  • IEnumerable データ ソースにバインドし、コントロール ツリーを構築するデータを列挙します。

  • GridViewDetailsView など、データ バインド コントロールの基本として機能します。

HierarchicalDataBoundControl

  • 階層形式でデータを表示するコントロールの基本クラスです。TreeViewMenu など、データ バインド ツリー ベースのコントロールの基本として機能します。

提供されるデータ バインディングのプロパティ

基本のデータ バインド コントロール クラスには、ページの開発時にデータ ソースをコントロールにバインドするために必要な、公開済みのデータ バインディング プロパティがあります。コントロールの作成者側では、追加の作業は必要ありません。カスタム コントロールは、たとえば DataBoundControl から派生すると、DataSourceIDDataSourceDataMember という 3 つの公開済みデータ バインディング プロパティを継承します。この場合、DataSource プロパティまたは DataSourceID プロパティの値を設定することで、コントロールがバインドするデータ ソースを指定できます。

DataSourceID プロパティを使用すると、データ バインド コントロールがデータを取得するデータ ソースを表すコントロールの ID を指定できます。

DataSource を使用すると、次に示す 2 種類のデータ オブジェクトにデータ バインド コントロールを直接バインドできます。

  • IEnumerable インターフェイスを実装するオブジェクト (ArrayArrayList、または Hashtable などのオブジェクト)。

  • IListSource インターフェイスを実装するオブジェクト (DataSet などのオブジェクト)。

  • DataMember プロパティなど、その他のデータ バインド プロパティを使用して、コントロールをバインドするデータ収集の部分を指定することもできます。

  • 各データ バインド コントロール クラスまたはデータ バインド基本クラスで公開されているデータ バインディング プロパティの詳細については、各クラスの説明を参照してください。

カスタム データ バインド プロパティの公開

カスタム コントロールのカスタム データ バインディング プロパティを公開する場合、または既存のデータ バインディング プロパティをオーバーライドする場合、コントロールが初期化済みであれば、OnDataPropertyChanged メソッドを呼び出します。こうすることで、新しいデータ バインディング プロパティ設定を使用できるように、データ バインド コントロールが強制的にデータに再バインドされます。

派生したデータ バインド コントロール クラスに所属するプロパティのコード例を次に示します。この例では、データ ソースを特定するプロパティがデータ バインド コントロールの初期化後に変更された場合に、データ バインド コントロールから OnDataPropertyChanged メソッドを呼び出す方法を示します。

Inherits DataBoundControl

Public Property DataTextField() As String
    Get
        Dim o As Object = ViewState("DataTextField")
        If o Is Nothing Then
            Return String.Empty
        Else
            Return CStr(o)
        End If
    End Get
    Set(ByVal value As String)
        ViewState("DataTextField") = value
        If (Initialized) Then
            OnDataPropertyChanged()
        End If
    End Set
End Property
public class SimpleDataBoundColumn : DataBoundControl
{
    public string DataTextField
    {
        get
        {
            object o = ViewState["DataTextField"];
            return ((o == null) ? string.Empty : (string)o);
        }
        set
        {
            ViewState["DataTextField"] = value;
            if (Initialized)
            {
                OnDataPropertyChanged();
            }
        }
    }

データ取得の開始

データの取得は、コントロールの基本データ バインド コントロールが継承した PerformSelect メソッドのオーバーライド内から開始されます。このオーバーライド内から、データの取得を呼び出し、返されるデータを処理するコールバック メソッドを指定します。

データを取得するには、オーバーライドした PerformSelect メソッドで次のタスクを実行します。

  1. ページ開発者が DataSource プロパティまたは DataSourceID プロパティを使用して、コントロールにバインドするデータを設定したかどうかを確認します。これは、IsBoundUsingDataSourceID プロパティを検証することで確認できます。たとえば、IsBoundUsingDataSourceID プロパティが false 設定の場合、DataSource プロパティがデータ ソースの指定に使用されたことを示します。

  2. ページ開発者が DataSource プロパティを設定した場合、OnDataBinding メソッドを呼び出すという追加の手順が必要です。

  3. GetData メソッドを呼び出して、データ バインド コントロールに関連付けられた DataSourceView オブジェクトを取得します。

  4. 取得した DataSourceViewSelect メソッドを呼び出してデータの取得を開始し、取得したデータを処理するコールバック メソッドを指定します。Select メソッドは非同期で動作するため、データの取得中に他の処理を実行できます。

  5. RequiresDataBinding プロパティ を false に設定してから、MarkAsDataBound メソッドを呼び出すことで、PerformSelect タスクの完了を指定します。

  6. OnDataBound イベントを発生します。

PerformSelect メソッドのオーバーライド内で、前のデータ取得タスクを完了するコード例を次に示します。

Protected Overrides Sub PerformSelect()
    ' Call OnDataBinding here if bound to a data source using the
    ' DataSource property (instead of a DataSourceID), because the
    ' databinding statement is evaluated before the call to GetData.       
    If Not IsBoundUsingDataSourceID Then
        OnDataBinding(EventArgs.Empty)
    End If

    ' The GetData method retrieves the DataSourceView object from  
    ' the IDataSource associated with the data-bound control.            
    GetData().Select(CreateDataSourceSelectArguments(), _
        AddressOf OnDataSourceViewSelectCallback)

    ' The PerformDataBinding method has completed.
    RequiresDataBinding = False
    MarkAsDataBound()

    ' Raise the DataBound event.
    OnDataBound(EventArgs.Empty)

End Sub
protected override void PerformSelect()
{
    // Call OnDataBinding here if bound to a data source using the
    // DataSource property (instead of a DataSourceID), because the
    // databinding statement is evaluated before the call to GetData.       
    if (!IsBoundUsingDataSourceID)
    {
        this.OnDataBinding(EventArgs.Empty);
    }

    // The GetData method retrieves the DataSourceView object from  
    // the IDataSource associated with the data-bound control.            
    GetData().Select(CreateDataSourceSelectArguments(),
        this.OnDataSourceViewSelectCallback);

    // The PerformDataBinding method has completed.
    RequiresDataBinding = false;
    MarkAsDataBound();

    // Raise the DataBound event.
    OnDataBound(EventArgs.Empty);
}

取得したデータの処理

取得したデータを受け入れるコールバック メソッドを作成します。これは、Select メソッドを PerformSelect メソッドのオーバーライド内から呼び出したときに指定したコールバック メソッドです。コールバック メソッドには、IEnumerable 型の 1 つのパラメータのみを含める必要があります。コールバック メソッドでは、コントロールの必要に応じて、戻り値を自由に処理できます。最後の手順として、PerformDataBinding メソッドを呼び出します。

IEnumerable 型のパラメータがあるコールバック メソッドのコード例を次に示します。このコールバック メソッドは PerformDataBinding メソッドを呼び出します。

Private Sub OnDataSourceViewSelectCallback(ByVal retrievedData As IEnumerable)
    ' Call OnDataBinding only if it has not already been 
    ' called in the PerformSelect method.
    If IsBoundUsingDataSourceID Then
        OnDataBinding(EventArgs.Empty)
    End If
    ' The PerformDataBinding method binds the data in the  
    ' retrievedData collection to elements of the data-bound control.
    PerformDataBinding(retrievedData)

End Sub
private void OnDataSourceViewSelectCallback(IEnumerable retrievedData)
{
    // Call OnDataBinding only if it has not already been 
    // called in the PerformSelect method.
    if (IsBoundUsingDataSourceID)
    {
        OnDataBinding(EventArgs.Empty);
    }
    // The PerformDataBinding method binds the data in the  
    // retrievedData collection to elements of the data-bound control.
    PerformDataBinding(retrievedData);
}

データを表す UI オブジェクトの作成

PerformDataBinding メソッドのオーバーライド内で、データを表す子コントロールを作成します。データ収集を列挙し、子コントロールを作成し、各データ項目に基づいてプロパティを設定します。新しい子コントロールをコントロールの Controls コレクションに追加することで、子コントロールが表示されます。コントロールの継承した Render メソッドで、コントロールの階層構造が表示されます。Render メソッドをオーバーライドすることで、カスタム コントロールに必要な特殊な表示方法を実行することもできます。たとえば、追加の HTML 要素を含めたり、デザイン モード時に特殊な表示方法にするなどです。

データを表現する UI オブジェクトを作成するには、PerformDataBinding メソッドをオーバーライドし、次のタスクを完了します。

  1. PerformDataBinding メソッドを呼び出して、他のコードがこのメソッドに依存して実行できるようにします。

  2. データ収集内のデータを列挙し、UI 表示でデータを表現する子コントロールを作成します。コントロールの Add メソッドを呼び出すことで、各子コントロールをコントロールのコレクションに追加します。

  • PerformDataBinding メソッドをオーバーライドするコード例を次に示します。PerformDataBinding メソッドを呼び出して、他のコードがこのメソッドに依存して実行できるようにします。データ収集が列挙され、UI 表示のデータを表す子コントロールが作成されます。
        Protected Overrides Sub PerformDataBinding(ByVal retrievedData As IEnumerable)
            MyBase.PerformDataBinding(retrievedData)

            ' Verify data exists.
            If Not (retrievedData Is Nothing) Then
                Dim tbl As New Table()
                Dim row As TableRow
                Dim cell As TableCell
                Dim dataStr As String = String.Empty

                Dim dataItem As Object
                For Each dataItem In retrievedData
                    ' If the DataTextField was specified get the data
                    ' from that field, otherwise get the data from the first field. 
                    If DataTextField.Length > 0 Then
                        dataStr = DataBinder.GetPropertyValue(dataItem, DataTextField, Nothing)
                    Else
                        Dim props As PropertyDescriptorCollection = TypeDescriptor.GetProperties(dataItem)
                        If props.Count >= 1 Then
                            If Nothing <> props(0).GetValue(dataItem) Then
                                dataStr = props(0).GetValue(dataItem).ToString()
                            End If
                        End If
                    End If

                    row = New TableRow()
                    tbl.Rows.Add(row)
                    cell = New TableCell()
                    cell.Text = dataStr
                    row.Cells.Add(cell)
                Next dataItem

                Controls.Add(tbl)
            End If

        End Sub
    End Class
End Namespace
protected override void PerformDataBinding(IEnumerable retrievedData)
{
    base.PerformDataBinding(retrievedData);

    // Verify data exists.
    if (retrievedData != null)
    {
        Table tbl = new Table();
        TableRow row;
        TableCell cell;
        string dataStr = String.Empty;

        foreach (object dataItem in retrievedData)
        {
            // If the DataTextField was specified get the data
            // from that field, otherwise get the data from the first field. 
            if (DataTextField.Length > 0)
            {
                dataStr = DataBinder.GetPropertyValue(dataItem,
                    DataTextField, null);
            }
            else
            {
                PropertyDescriptorCollection props =
                        TypeDescriptor.GetProperties(dataItem);
                if (props.Count >= 1)
                {
                    if (null != props[0].GetValue(dataItem))
                    {
                        dataStr = props[0].GetValue(dataItem).ToString();
                    }
                }
            }

            row = new TableRow();
            tbl.Rows.Add(row);
            cell = new TableCell();
            cell.Text = dataStr;
            row.Cells.Add(cell);
        }

        this.Controls.Add(tbl); 
    }
}

カスタム サーバー コントロールのビルド

カスタム データ バインド Web サーバー コントロールをビルドする方法と Web ページで使用する方法の詳細については、「カスタム サーバー コントロールの例のビルド」を参照してください。

参照

処理手順

チュートリアル : ASP.NET 2.0 用カスタム データ バインド ASP.NET Web コントロールの作成

チュートリアル : カスタム サーバー コントロールの開発と使用

概念

ASP.NET のデータ バインド Web サーバー コントロールの概要

カスタム サーバー コントロールのメタデータ属性

ASP.NET コントロール デザイナの概要

参照

HierarchicalDataBoundControlDesigner

その他の技術情報

ASP.NET カスタム サーバー コントロールの開発