次の方法で共有


データを操作する

データ ソース内のレコード間を移動する最も簡単な方法は、 BindingSource コンポーネントをデータ ソースにバインドしてから、コントロールを BindingSourceにバインドすることです。 その後、BindingSourceMoveNextMoveLastMovePreviousなど、MoveFirstの組み込みのナビゲーション方法を使用できます。 これらのメソッドを使用すると、PositionCurrent プロパティと BindingSource プロパティが適切に調整されます。 Position プロパティを設定して、レコードを検索し、現在のレコードとして設定することもできます。

データ ソース内のレコード位置をインクリメントするには

バインドされたデータのPositionBindingSourceプロパティをレコード位置に設定して、必要なレコード位置に移動します。 次の例では、MoveNextBindingSource メソッドを使用して、Positionを選択したときにnextButton プロパティをインクリメントする方法を示します。 BindingSource は、データセット CustomersNorthwind テーブルに関連付けられています。

private void nextButton_Click(object sender, System.EventArgs e)
{
    this.customersBindingSource.MoveNext();
}
Private Sub nextButton_Click(ByVal sender As Object,
    ByVal e As System.EventArgs) Handles nextButton.Click
    Me.customersBindingSource.MoveNext()
End Sub

Position プロパティを最初のレコードまたは最後のレコードを超える値に設定してもエラーは発生しません。Windows フォームでは、リストの範囲外の値に位置が設定されないためです。 最初のレコードと最後のレコードのどちらを超えたかを把握することが重要な場合は、データ要素の数を超えるかどうかをテストするロジックを含めます。

最初のレコードまたは最後のレコードを超えたかどうかを確認するには

PositionChanged イベントのイベント ハンドラーを作成します。 ハンドラーでは、提案された位置の値が実際のデータ要素数を超えたかどうかをテストできます。

次の例は、最後のデータ要素に到達したかどうかをテストする方法を示しています。 この例では、最後の要素にいる場合は、フォームの [次へ] ボタン 無効になります。

void customersBindingSource_PositionChanged(object sender, EventArgs e)
{
    if (customersBindingSource.Position == customersBindingSource.Count - 1)
        nextButton.Enabled = false;
    else
        nextButton.Enabled = true;
}
Sub customersBindingSource_PositionChanged(ByVal sender As Object,
    ByVal e As EventArgs)

    If customersBindingSource.Position =
        customersBindingSource.Count - 1 Then
        nextButton.Enabled = False
    Else
        nextButton.Enabled = True
    End If
End Sub

コード内で移動するリストを変更する場合は、[ 次へ ] ボタンを再度有効にして、ユーザーが新しいリストの長さ全体を参照できるようにする必要があることに注意してください。 さらに、操作している特定の PositionChanged に対する上記の BindingSource イベントは、そのイベント処理メソッドに関連付ける必要があることに注意してください。

レコードを検索して現在のアイテムとして設定するには

現在のアイテムとして設定するレコードを見つけます。 データ ソースでFindが実装されている場合は、例に示すように、BindingSourceIBindingList メソッドを使用します。 IBindingList を実装するデータ ソースの例としては、BindingList<T>DataViewがあります。

void findButton_Click(object sender, EventArgs e)
{
    int foundIndex = customersBindingSource.Find("CustomerID", "ANTON");
    customersBindingSource.Position = foundIndex;
}
Sub findButton_Click(ByVal sender As Object, ByVal e As EventArgs) _
    Handles findButton.Click
    Dim foundIndex As Integer = customersBindingSource.Find("CustomerID",
        "ANTON")
    customersBindingSource.Position = foundIndex
End Sub

子テーブルで選択した行が正しい位置に維持されるようにするには

Windows フォームでデータ バインディングを操作すると、親/子ビューまたはマスター/詳細ビューにデータが表示されます。 これは、同じソースのデータが 2 つのコントロールに表示されるデータ バインディング シナリオです。 1 つのコントロールで選択を変更すると、2 番目のコントロールに表示されるデータが変更されます。 たとえば、1 つ目のコントロールには顧客のリストが含まれており、2 番目のコントロールには、選択した顧客に関連する注文の一覧が含まれている場合があります。

親/子ビューにデータを表示する場合は、子テーブルで現在選択されている行がテーブルの最初の行にリセットされないように、追加の手順を実行する必要がある場合があります。 これを行うには、子テーブルの位置をキャッシュし、親テーブルの変更後にリセットする必要があります。 通常、子テーブルのリセットは、親テーブルの行のフィールドが初めて変更された場合に発生します。

現在の子テーブルの位置をキャッシュするには

  1. 子テーブルの位置を格納する整数変数と、子テーブルの位置をキャッシュするかどうかを格納するブール変数を宣言します。

    private int cachedPosition = -1;
    private bool cacheChildPosition = true;
    
    Private cachedPosition As Integer = -1
    Private cacheChildPosition As Boolean = True
    
  2. バインドのListChangedCurrencyManager イベントを処理し、ListChangedTypeResetを確認します。

  3. CurrencyManagerの現在位置を確認します。 リストの最初のエントリ (通常は 0) より大きい場合は、変数に保存します。

    void relatedCM_ListChanged(object sender, ListChangedEventArgs e)
    {
        // Check to see if this is a caching situation.
        if (cacheChildPosition && cachePositionCheckBox.Checked)
        {
            // If so, check to see if it is a reset situation, and the current
            // position is greater than zero.
            CurrencyManager relatedCM = sender as CurrencyManager;
            if (e.ListChangedType == ListChangedType.Reset && relatedCM.Position > 0)
    
                // If so, cache the position of the child table.
                cachedPosition = relatedCM.Position;
        }
    }
    
    Private Sub relatedCM_ListChanged(ByVal sender As Object,
        ByVal e As ListChangedEventArgs)
        ' Check to see if this is a caching situation.
        If cacheChildPosition AndAlso cachePositionCheckBox.Checked Then
            ' If so, check to see if it is a reset situation, and the current
            ' position is greater than zero.
            Dim relatedCM As CurrencyManager = sender
            If e.ListChangedType = ListChangedType.Reset _
                AndAlso relatedCM.Position > 0 Then
    
                ' If so, cache the position of the child table.
                cachedPosition = relatedCM.Position
            End If
        End If
    
    End Sub
    
  4. 親通貨マネージャーの親リストの CurrentChanged イベントを処理します。 ハンドラーで、キャッシュ シナリオではないことを示すブール値を設定します。 CurrentChangedが発生した場合、親への変更はリスト位置の変更であり、項目値の変更ではありません。

    void bindingSource1_CurrentChanged(object sender, EventArgs e)
    {
        // If the CurrentChanged event occurs, this is not a caching
        // situation.
        cacheChildPosition = false;
    }
    
    ' Handle the current changed event. This event occurs when
    ' the current item is changed, but not when a field of the current
    ' item is changed.
    Private Sub bindingSource1_CurrentChanged(ByVal sender As Object,
        ByVal e As EventArgs) Handles bindingSource1.CurrentChanged
        ' If the CurrentChanged event occurs, this is not a caching 
        ' situation.
        cacheChildPosition = False
    
    End Sub
    

子テーブルの位置をリセットする方法

  1. 子テーブル バインドのPositionChangedCurrencyManager イベントを処理します。

  2. 子テーブルの位置を、前の手順で保存したキャッシュされた位置にリセットします。

    void relatedCM_PositionChanged(object sender, EventArgs e)
    {
        // Check to see if this is a caching situation.
        if (cacheChildPosition && cachePositionCheckBox.Checked)
        {
            CurrencyManager relatedCM = sender as CurrencyManager;
    
            // If so, check to see if the current position is
            // not equal to the cached position and the cached
            // position is not out of bounds.
            if (relatedCM.Position != cachedPosition && cachedPosition
                > 0 && cachedPosition < relatedCM.Count)
            {
                relatedCM.Position = cachedPosition;
                cachedPosition = -1;
            }
        }
    }
    
    Private Sub relatedCM_PositionChanged(ByVal sender As Object, ByVal e As EventArgs)
        ' Check to see if this is a caching situation.
        If cacheChildPosition AndAlso cachePositionCheckBox.Checked Then
            Dim relatedCM As CurrencyManager = sender
    
            ' If so, check to see if the current position is 
            ' not equal to the cached position and the cached 
            ' position is not out of bounds.
            If relatedCM.Position <> cachedPosition AndAlso
                cachedPosition > 0 AndAlso cachedPosition <
                relatedCM.Count Then
                relatedCM.Position = cachedPosition
                cachedPosition = -1
            End If
        End If
    End Sub
    

コード例をテストするには、次の手順を実行します。

  1. 例を実行します。

  2. [ キャッシュとリセット位置 ] チェック ボックスがオンになっていることを確認します。

  3. 親テーブルのフィールドを変更するには、[ 親フィールドのクリア ] ボタンを選択します。 子テーブルで選択した行が変更されない点に注意してください。

  4. 例を閉じて再実行します。 リセット動作は親行の最初の変更でのみ発生するため、もう一度実行する必要があります。

  5. [ キャッシュとリセット位置 ] チェック ボックスをオフにします。

  6. [ 親フィールドのクリア ] ボタンを選択します。 子テーブルで選択されている行が最初の行に変わります。

こちらも参照ください