Compartilhar via


Navegar pelos dados (Windows Forms .NET)

A maneira mais fácil de navegar pelos registros em uma fonte de dados é associar um componente BindingSource à fonte de dados e associar controles ao BindingSource. Em seguida, você pode usar o método de navegação interno do BindingSource, como MoveNext, MoveLast, MovePreviouse MoveFirst. O uso desses métodos ajustará as propriedades Position e Current do BindingSource adequadamente. Você também pode encontrar um registro e defini-lo como o registro atual definindo a propriedade Position.

Para incrementar a posição do registro em uma fonte de dados

Defina a propriedade Position do BindingSource para os dados associados, ajustando a posição do registro para alcançar a posição de registro necessária. O exemplo a seguir ilustra o uso do método MoveNext do BindingSource para incrementar a propriedade Position ao selecionar o nextButton. O BindingSource está associado à tabela Customers de um conjunto de dados Northwind.

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

Nota

Definir a propriedade Position como um valor além do primeiro ou último registro não resulta em um erro, pois o Windows Forms não definirá a posição como um valor fora dos limites da lista. Se for importante saber se você passou do primeiro ou último registro, inclua a lógica para testar se você excederá a contagem de elementos de dados.

Para verificar se você passou o limite do primeiro ou do último registro

Crie um manipulador de eventos para o evento PositionChanged. No manipulador, você pode testar se o valor de posição proposto excedeu a contagem real de elementos de dados.

O exemplo a seguir ilustra como você pode testar se atingiu o último elemento de dados. No exemplo, se você estiver no último elemento, o botão Próximo no formulário será desabilitado.

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

Nota

Lembre-se de que, se você alterar a lista que está navegando no código, deverá habilitar novamente o botão Próximo para que os usuários possam navegar por todo o comprimento da nova lista. Além disso, lembre-se de que o evento PositionChanged acima, referente ao BindingSource específico em que você está trabalhando, precisa ser associado ao seu método de tratamento de eventos.

Para localizar um registro e defini-lo como o item atual

Localize o registro que você deseja definir como o item atual. Use o método Find do BindingSource, conforme mostrado no exemplo, se a fonte de dados implementar IBindingList. Alguns exemplos de fontes de dados que implementam IBindingList são BindingList<T> e 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

Para garantir que a linha selecionada em uma tabela filha permaneça na posição correta

Ao trabalhar com a associação de dados no Windows Forms, você exibirá dados em uma exibição pai/filho ou mestre/detalhe. É um cenário de associação de dados em que os dados da mesma fonte são exibidos em dois controles. Alterar a seleção em um controle faz com que os dados exibidos no segundo controle sejam alterados. Por exemplo, o primeiro controle pode conter uma lista de clientes e o segundo uma lista de pedidos relacionados ao cliente selecionado no primeiro controle.

Ao exibir dados em um modo de exibição pai/filho, talvez seja necessário executar etapas extras para garantir que a linha atualmente selecionada na tabela filho não seja redefinida para a primeira linha da tabela. Para fazer isso, você precisará armazenar em cache a posição da tabela filha e redefini-la depois que a tabela mãe for alterada. Normalmente, a redefinição da tabela filho ocorre na primeira vez que um campo em uma linha da tabela pai é alterado.

Para armazenar em cache a posição atual da tabela filha

  1. Declare uma variável inteira para armazenar a posição da tabela filho e uma variável booleana para indicar se deve armazenar em cache a posição da tabela filho.

    private int cachedPosition = -1;
    private bool cacheChildPosition = true;
    
    Private cachedPosition As Integer = -1
    Private cacheChildPosition As Boolean = True
    
  2. Manipule o evento ListChanged para a vinculação de CurrencyManager e verifique se há um ListChangedType de Reset.

  3. Verifique a posição atual do CurrencyManager. Se for maior que a primeira entrada da lista (normalmente 0), salve-a em uma variável.

    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. Manipule o evento CurrentChanged da lista pai para o gerenciador de moeda principal. No manipulador, defina o valor booliano para indicar que não é um cenário de cache. Se o CurrentChanged ocorrer, a alteração no elemento pai será uma alteração de posição de lista e não uma alteração de valor de item.

    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
    

Para redefinir a posição da tabela filha

  1. Manipule o evento PositionChanged no CurrencyManagerda associação da tabela filha.

  2. Redefina a posição da tabela filha para a posição armazenada em cache salva no procedimento anterior.

    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
    

Para testar o exemplo de código, execute as seguintes etapas:

  1. Execute o exemplo.

  2. Verifique se a Cache e a posição de redefinição caixa de seleção está selecionada.

  3. Selecione o botão Limpar campo pai para provocar uma alteração em um campo da tabela pai. Observe que a linha selecionada na tabela filha não é alterada.

  4. Feche e execute novamente o exemplo. Você precisa executá-lo novamente porque o comportamento de redefinição ocorre apenas na primeira alteração feita na linha pai.

  5. Limpe o cache e redefina a caixa de seleção da posição.

  6. Selecione o botão Limpar o campo pai. Observe que a linha selecionada na tabela filha muda para a primeira linha.

Consulte também