次の方法で共有


Visual Studio を使用して .NET Framework アプリケーションのデータ ソースとしてオブジェクトをバインドする

DataSet クラスと関連クラスは、アプリケーションがデータベースから切断されている間にアプリケーションがメモリ内のデータを操作できるようにする、2000 年代初頭のレガシ .NET Framework テクノロジです。 このテクノロジは、ユーザーがデータを変更し、変更をデータベースに保持できるアプリに特に役立ちます。 データセットは実証済みの成功したテクノロジですが、新しい .NET アプリケーションには Entity Framework Core を使用することをお勧めします。 Entity Framework は、オブジェクト モデルとして表形式データを操作するより自然な方法を提供し、よりシンプルなプログラミング インターフェイスを備えています。

Visual Studio には、アプリケーションのデータ ソースとしてカスタム オブジェクトを操作するためのデザイン時ツールが用意されています。 UI コントロールにバインドするオブジェクトにデータベースのデータを格納する場合は、Entity Framework を使用してクラスまたはクラスを生成することをお勧めします。 Entity Framework では、すべての定型変更追跡コードが自動生成されます。つまり、DbSet オブジェクトで AcceptChanges を呼び出すと、ローカル オブジェクトへの変更がデータベースに自動的に永続化されます。 詳細については、 Entity Framework のドキュメントを参照してください

ヒント

この記事のオブジェクト バインディングへのアプローチは、アプリケーションが既にデータセットに基づいている場合にのみ考慮する必要があります。 データセットに既に慣れている場合や、処理するデータが表形式であり、複雑すぎたり大きすぎたりしない場合にも、これらのアプローチを使用できます。 さらに簡単な例として、DataReader を使用してオブジェクトに直接データを読み込み、データ バインドなしで UI を手動で更新する方法については、「 ADO.NET を使用して単純なデータ アプリケーションを作成する」を参照してください。

オブジェクトの要件

Visual Studio でカスタム オブジェクトがデータ デザイン ツールを操作するための唯一の要件は、オブジェクトに少なくとも 1 つのパブリック プロパティが必要であるということです。

一般に、カスタム オブジェクトでは、アプリケーションのデータ ソースとして機能する特定のインターフェイス、コンストラクター、または属性は必要ありません。 ただし、[ データ ソース] ウィンドウからデザインサーフェイスにオブジェクトをドラッグしてデータ バインド コントロールを作成する場合、オブジェクトが ITypedList または IListSource インターフェイスを実装する場合は、オブジェクトに既定のコンストラクターが必要です。 それ以外の場合、Visual Studio はデータ ソース オブジェクトをインスタンス化できず、デザイン画面に項目をドラッグするとエラーが表示されます。

カスタム オブジェクトをデータ ソースとして使用する例

データ ソースとしてオブジェクトを操作するときにアプリケーション ロジックを実装する方法は数え切れないほどありますが、SQL データベースでは、Visual Studio で生成された TableAdapter オブジェクトを使用して簡略化できる標準操作がいくつかあります。 このページでは、TableAdapters を使用してこれらの標準プロセスを実装する方法について説明します。 これは、カスタム オブジェクトを作成するためのガイドとして意図されていません。 たとえば、通常、オブジェクトの特定の実装やアプリケーションのロジックに関係なく、次の標準操作を実行します。

  • オブジェクトへのデータの読み込み (通常はデータベースから)。

  • オブジェクトの型指定コレクションの作成。

  • コレクションへのオブジェクトの追加とコレクションからのオブジェクトの削除。

  • フォーム上のユーザーにオブジェクト データを表示する。

  • オブジェクト内のデータの変更/編集。

  • オブジェクトからデータベースにデータを保存します。

オブジェクトにデータを読み込む

この例では、TableAdapters を使用してオブジェクトにデータを読み込みます。 既定では、TableAdapters は、データベースからデータをフェッチしてデータ テーブルを設定する 2 種類のメソッドを使用して作成されます。

  • TableAdapter.Fill メソッドは、返されたデータを既存のデータ テーブルに入力します。

  • TableAdapter.GetData メソッドは、データが設定された新しいデータ テーブルを返します。

カスタム オブジェクトをデータと共に読み込む最も簡単な方法は、 TableAdapter.GetData メソッドを呼び出し、返されたデータ テーブル内の行のコレクションをループ処理し、各オブジェクトに各行の値を設定することです。 TableAdapter に追加されたクエリに対して設定されたデータ テーブルを返す GetData メソッドを作成できます。

Visual Studio では、TableAdapter クエリに既定で Fill および GetData 名前が付けられますが、これらの名前は任意の有効なメソッド名に変更できます。

次の例は、データ テーブル内の行をループ処理し、オブジェクトにデータを設定する方法を示しています。

private void LoadCustomers()
{
    NorthwindDataSet.CustomersDataTable customerData = 
        customersTableAdapter1.GetTop5Customers();
    
    foreach (NorthwindDataSet.CustomersRow customerRow in customerData)
    {
        Customer currentCustomer = new Customer();
        currentCustomer.CustomerID = customerRow.CustomerID;
        currentCustomer.CompanyName = customerRow.CompanyName;

        if (customerRow.IsAddressNull() == false)
        {
            currentCustomer.Address = customerRow.Address;
        }

        if (customerRow.IsCityNull() == false)
        {
            currentCustomer.City = customerRow.City;
        }

        if (customerRow.IsContactNameNull() == false)
        {
            currentCustomer.ContactName = customerRow.ContactName;
        }

        if (customerRow.IsContactTitleNull() == false)
        {
            currentCustomer.ContactTitle = customerRow.ContactTitle;
        }

        if (customerRow.IsCountryNull() == false)
        {
            currentCustomer.Country = customerRow.Country;
        }

        if (customerRow.IsFaxNull() == false)
        {
            currentCustomer.Fax = customerRow.Fax;
        }

        if (customerRow.IsPhoneNull() == false)
        {
            currentCustomer.Phone = customerRow.Phone;
        }

        if (customerRow.IsPostalCodeNull() == false)
        {
            currentCustomer.PostalCode = customerRow.PostalCode;
        }

        if (customerRow.IsRegionNull() == false)
        {
            currentCustomer.Region = customerRow.Region;
        }

        LoadOrders(currentCustomer);
        customerBindingSource.Add(currentCustomer);
    }
}

オブジェクトのコレクションを型指定して作成する

オブジェクトのコレクション クラスを作成することも、 BindingSource コンポーネントによって自動的に提供される型指定されたコレクションを使用することもできます。

オブジェクトのカスタム コレクション クラスを作成するときは、 BindingList<T>から継承することをお勧めします。 このジェネリック クラスは、コレクションを管理する機能と、Windows フォームのデータ バインディング インフラストラクチャに通知を送信するイベントを発生させる機能を提供します。

BindingSourceで自動的に生成されたコレクションは、型指定されたコレクションにBindingList<T>を使用します。 アプリケーションで追加の機能が必要ない場合は、 BindingSource内でコレクションを維持できます。 詳細については、BindingSource クラスの List プロパティを参照してください。

コレクションに BindingList<T>の基本実装によって提供されない機能が必要な場合は、必要に応じてクラスに追加できるようにカスタム コレクションを作成する必要があります。

次のコードは、 Order オブジェクトの厳密に型指定されたコレクションのクラスを作成する方法を示しています。

/// <summary>
/// A collection of Orders
/// </summary>
public class Orders: System.ComponentModel.BindingList<Order>
{
    // Add any additional functionality required by your collection.
}

コレクションにオブジェクトを追加する

カスタム コレクション クラスまたはBindingSourceAdd メソッドを呼び出して、コレクションにオブジェクトを追加します。

Add メソッドは、BindingList<T>から継承すると、カスタム コレクションに対して自動的に提供されます。

次のコードは、 BindingSourceで型指定されたコレクションにオブジェクトを追加する方法を示しています。

Customer currentCustomer = new Customer();
customerBindingSource.Add(currentCustomer);

次のコードは、 BindingList<T>から継承する型指定されたコレクションにオブジェクトを追加する方法を示しています。

この例では、 Orders コレクションは Customer オブジェクトのプロパティです。

Order currentOrder = new Order();
currentCustomer.Orders.Add(currentOrder);

コレクションからオブジェクトを削除する

コレクションからオブジェクトを削除するには、カスタム コレクション クラスまたはBindingSourceRemoveまたはRemoveAtメソッドを呼び出します。

RemoveメソッドとRemoveAt メソッドは、BindingList<T>から継承すると、カスタム コレクションに対して自動的に提供されます。

次のコードは、RemoveAt メソッドを使用して、BindingSourceで型指定されたコレクションからオブジェクトを見つけて削除する方法を示しています。

int customerIndex = customerBindingSource.Find("CustomerID", "ALFKI");
customerBindingSource.RemoveAt(customerIndex);

ユーザーにオブジェクト データを表示する

オブジェクト内のデータをユーザーに表示するには、データ ソース構成ウィザードを使用してオブジェクト データ ソースを作成し、[データ ソース] ウィンドウからオブジェクト全体または個々のプロパティをフォームにドラッグします。

オブジェクト内のデータを変更する

Windows フォーム コントロールにデータバインドされたカスタム オブジェクトのデータを編集するには、バインドされたコントロール (またはオブジェクトのプロパティで直接) のデータを編集するだけです。 データ バインディング アーキテクチャは、オブジェクト内のデータを更新します。

アプリケーションで変更の追跡と、提案された変更の元の値へのロールバックが必要な場合は、オブジェクト モデルにこの機能を実装する必要があります。 データ テーブルが提案された変更を追跡する方法の例については、「 DataRowStateHasChanges、および GetChanges」を参照してください。

オブジェクト内のデータをデータベースに保存し直す

オブジェクトの値を TableAdapter の DBDirect メソッドに渡して、データをデータベースに保存します。

Visual Studio は、データベースに対して直接実行できる DBDirect メソッドを作成します。 これらのメソッドには、DataSet オブジェクトまたは DataTable オブジェクトは必要ありません。

TableAdapter DBDirect メソッド 説明
TableAdapter.Insert データベースに新しいレコードを追加します。これにより、個々の列値をメソッド パラメーターとして渡すことができます。
TableAdapter.Update データベース内の既存のレコードを更新します。 Update メソッドは、元の列と新しい列の値をメソッド パラメーターとして受け取ります。 元の値を使用して元のレコードを検索し、新しい値を使用してそのレコードを更新します。

TableAdapter.Update メソッドは、DataRowDataSetDataTableDataRow、または配列をメソッド パラメーターとして取得することで、データセットの変更をデータベースにリコンサイルするためにも使用されます。
TableAdapter.Delete メソッド パラメーターとして渡された元の列値に基づいて、データベースから既存のレコードを削除します。

オブジェクトのコレクションからデータを保存するには、オブジェクトのコレクションをループ処理します (たとえば、for-next ループを使用)。 TableAdapter の DBDirect メソッドを使用して、各オブジェクトの値をデータベースに送信します。

次の例は、 TableAdapter.Insert DBDirect メソッドを使用して新しい顧客をデータベースに直接追加する方法を示しています。

private void AddNewCustomers(Customer currentCustomer)
{
    customersTableAdapter.Insert( 
        currentCustomer.CustomerID, 
        currentCustomer.CompanyName, 
        currentCustomer.ContactName, 
        currentCustomer.ContactTitle, 
        currentCustomer.Address, 
        currentCustomer.City, 
        currentCustomer.Region, 
        currentCustomer.PostalCode, 
        currentCustomer.Country, 
        currentCustomer.Phone, 
        currentCustomer.Fax);
}
  • Visual Studio でコントロールをデータにバインドする