次の方法で共有


データ間を移動する (Windows フォーム .NET)

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

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

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

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

注意

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

レコードを検索し、現在の項目として設定するには

現在のアイテムとして設定したいレコードを探します。 データ ソースが IBindingList を実装している場合は、例に示すように BindingSourceFind メソッドを使います。 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 のコントロールで選択された顧客に関連する注文リストが含まれます。

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

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

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

    private int cachedPosition = -1;
    private bool cacheChildPosition = true;
    
    Private cachedPosition As Integer = -1
    Private cacheChildPosition As Boolean = True
    
  2. バインディングの CurrencyManagerListChanged イベントを処理し、ResetListChangedType をチェックします。

  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. 子テーブル バインディングの CurrencyManager に関する PositionChanged イベントを処理します。

  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. 必ず [Cache and reset position] (位置をキャッシュしてリセットする) チェックボックスをオンにします。

  3. [Clear parent field] (親フィールドのクリア) ボタンを選んで親テーブルのフィールドを変更します。 子テーブル内の選択行が変更されないことに注目してください。

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

  5. [Cache and reset position] (位置をキャッシュしてリセットする) チェックボックスをオフにします。

  6. [Clear parent field] (親フィールドのクリア) ボタンを選びます。 子テーブル内の選択行が 1 行目に変更されることに注目してください。

関連項目