导航数据(Windows 窗体 .NET)

在数据源中浏览记录的最简单方法是将 BindingSource 组件绑定到数据源,然后将控件绑定到 BindingSource。 然后,可以在 BindingSource 上使用内置导航方法,例如 MoveNextMoveLastMovePreviousMoveFirst。 使用这些方法会相应地调整 BindingSourcePositionCurrent 属性。 还可以通过设置 Position 属性找到一条记录并将其设置为当前记录。

递增数据源中的记录位置

将绑定数据的 BindingSourcePosition 属性设置为可转到必需记录位置的记录位置。 以下示例演示了在选择 nextButton 时使用 BindingSourceMoveNext 方法递增 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 Forms 不会将位置设置为列表边界之外的值。 如果必须知道是否已超过第一条或最后一条记录,请包含用于测试是否会超过数据元素计数的逻辑。

检查是否已超过第一条或最后一条记录

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 窗体中使用数据绑定时,将显示父/子视图或母版/详细视图中的数据。 它是指一个数据绑定方案,其中来自同一源的数据将显示在两个控件中。 更改一个控件中的选定内容会导致在第二个控件中显示的数据变动。 例如,第一个控件可能会包含一个客户列表,而第二个控件则可能包含与第一个控件中选定客户相关的订单列表。

当在父/子视图中显示数据时,可能需要采取额外步骤来确保子表中当前所选的行不会重置为表的第一行。 为了执行此操作,必须缓存子表位置并在父表发生更改后将其重置。 父表某一行中的字段第一次更改时通常会发生子表重置。

缓存当前子表位置

  1. 声明一个整数变量,以存储子表位置,并声明一个布尔变量,以存储是否缓存子表位置。

    private int cachedPosition = -1;
    private bool cacheChildPosition = true;
    
    Private cachedPosition As Integer = -1
    Private cacheChildPosition As Boolean = True
    
  2. 为绑定的 CurrencyManager 处理 ListChanged 事件并检查 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. 请确保“缓存并重置位置”复选框处于选中状态。

  3. 选择“清除父字段”按钮会导致父表的某个字段发生更改。 请注意,子表中的所选行将不会更改。

  4. 关闭并重新运行示例。 需要再次运行,原因是重置行为仅在父行中第一次更改时发生。

  5. 清除“缓存并重置位置”复选框。

  6. 选择“清除父字段”按钮。 请注意,子表中的选定的行将更改为第一行。

另请参阅