1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

VB.NET 2008 - Textbox & Listbox

Discussão em 'Programação' iniciada por H4LLoW, 24 de Maio de 2009. (Respostas: 17; Visualizações: 5194)

  1. H4LLoW

    H4LLoW Power Member

    Olá a todos!

    Precisava da ajuda dos entendidos, estou a tentar usar uma textbox para filtrar os dados de uma listbox. Já tenho definida a propriedade AutoCompleteCustomSource,
    e o AutoCompleteMode está definido para Append da textbox e está a funcionar perfeitamente.

    Agora o que queria fazer era definir uma função que através do evento _textchange da textbox me apresenta-se as opções possíveis na listbox.

    Este é o código que estou a utilizar mas cada vez que digito algo na textbox aparece uma janela a dizer "DataTable must be set prior to using dataview".

    Código:
    Private Sub txtSrch_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtSrch.TextChanged
    
            cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=cntbl.mdb"
            Try
                cn.Open()
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
    
            lstFrnc.Items.Clear()
            cm.Connection = cn
            cm.CommandText = "select * from tblfrnc where frnc_nm like '" & txtSrch.Text & "%'"
            rd = cm.ExecuteReader()
            lstFrnc.Items.Clear()
    
            While (rd.Read)
                lstFrnc.Items.Add(rd("frnc_nm"))
            End While
    
            rd.Close()
    
            If lstFrnc.Items.Count > 0 Then
                lstFrnc.SelectedIndex = 0
            End If
    
            Try
    
                Dim adp As New Data.OleDb.OleDbDataAdapter
                Dim ds As New DataSet
                Dim dv As New DataView
    
                adp.SelectCommand = cm
                adp.Fill(ds, "dataset")
                dv.Table = ds.Tables("tblFrnc")
                dv.Sort = "frnc_nm"
                lstFrnc.DataSource = dv
                lstFrnc.Refresh()
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            Finally
                cn.Close()
            End Try
        End Sub
    Qualquer ajuda é bem vinda.
     
  2. Thorak

    Thorak Power Member

    E em que linha é que a execução pára ?
     
  3. H4LLoW

    H4LLoW Power Member

    Não chega sequer a parar, a janela aparecia a cada vez que havia uma alteração na textbox, mas já improvisei uma solução,
    talvez não seja tecnicamente a mais correcta mas deixou de aparecer a janela com o aviso, e agora tudo parece funcionar como intencionado.

    A solução foi:

    Código:
    Private Sub txtSrch_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtSrch.TextChanged
    
            cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=cntbl.mdb"
            Try
                cn.Open()
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
    
            lstFrnc.Items.Clear()
            cm.Connection = cn
            cm.CommandText = "select * from tblfrnc where frnc_nm like '" & txtSrch.Text & "%'"
            rd = cm.ExecuteReader()
            lstFrnc.Items.Clear()
    
            While (rd.Read)
                lstFrnc.Items.Add(rd("frnc_nm"))
            End While
    
            rd.Close()
    
            If lstFrnc.Items.Count > 0 Then
                lstFrnc.SelectedIndex = 0
            End If
    
            Try
    [COLOR="DarkGreen"]'******Removido**********[/COLOR]
    [COLOR="DarkGreen"]            'Dim adp As New Data.OleDb.OleDbDataAdapter
                'Dim ds As New DataSet
                'Dim dv As New DataView
    
                'adp.SelectCommand = cm
                'adp.Fill(ds, "dataset")
                'dv.Table = ds.Tables("tblFrnc")
                'dv.Sort = "frnc_nm"
                'lstFrnc.DataSource = dv
                'lstFrnc.Refresh()[/COLOR]
    [COLOR="DarkGreen"]'******Removido**********[/COLOR]
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            Finally
                cn.Close()
            End Try
        End Sub
    Agora precisava de ajuda no código associado á acção _SelectedIndexChanged da listbox.
    O código em baixo permite preencher uma textbox com o nome seleccionado na listbox, mas queria preencher mais 5 textboxs, respectivamente:

    txtmorada
    txtlocalidade
    txtcp
    txtpais
    txtnif


    Código:
    Private Sub lstFrnc_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles lstFrnc.SelectedIndexChanged
            ' obtem o nome selecionado no listbox
            txtNome.Text = lstFrnc.SelectedItem
    End Sub
    Desde já o meu muito obrigado!
     
  4. PNDmartins

    PNDmartins Power Member

    Epá, já vi várias vezes isto e não me consigo a conter mais a fazer esta pergunta:

    Porque raio é que quando estão a preencher algum objecto com dados vindos do Sql usam o DataReader e lêem linha a linha os dados da base de dados???

    Pergunto isto porque, a meu ver, é extremamente mau. Além de, ler os dados linha a linha, torna o processo mais lento, se por alguma razão cair a ligação, está tudo tramado, lá se tem que reiniciar a máquina, e o servidor de sql (caso esteja a parte) porque como a ligação vai continuar aberta, o Server pode-se recusar a aceitar outra ligação (depende das configurações do servidor).

    Já estou a imaginar numa empresa onde tive onde reiniciar um server levava cerca de 30 minutos.

    Há formas bem mais fáceis e rápidas de fazer a ligação e muita gente insiste nisto.. ou sou eu que estou muito enganado ou então não sei..

    Se me pudesses esclarecer-me agradecia.

    Em relação ao teu problema, da forma como estás a fazer as coisas não estou a ver solução.
     
  5. H4LLoW

    H4LLoW Power Member

    Eu até compreendo que o meu código possa parecer desconexo, mas têm uma razão... eu sou novo por estas andanças e acima de tudo um autodidacta.
    Achei por bem pegar no visual basics (linguagem que me parece mais acessivel) e fazer um programa que me facilite as coisas no local de trabalho.
    Assim delineei todo o funcionamento da aplicação e esquematizei o desenho do interface.

    Agora estou na fase de passar para código aquilo que pretendo que cada elemento do interface efectue.
    Como os meus conhecimentos ainda são escassos vou procurando pela net formas de executar o que pretendo,
    tenho noção que há formas bem mais eficientes de executar o que pretendo, e estou aberto a todos os conselhos e opiniões,
    afinal estou aqui com o intuito de aprender!
     
  6. PNDmartins

    PNDmartins Power Member

    Porreiro.. Eu não disse o que disse com intuito de criticar mas sim por curiosidade.

    Podes fazer o mesmo com este código:

    Código:
     cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=cntbl.mdb"
     cm.ConnectionString = cn
     cm.CommandText = "select * from tblfrnc where frnc_nm like '" & txtSrch.Text & "%'"
     
     Dim Adp as new SqlDataAdapter(cm)
     Dim Dt as new DataTable
     
     Adp.fill(Dt)
     
     lstfrnc.DataSource = Dt
    
    As vantagens deste pedaço de código são:
    - O objecto Adp abre a connecção e fecha conforme precisa dela.
    - Ficas com um objecto DataTable (O Dt) em memória (dentro da sub porque foi declarado como dim) durante a execução da mesma e se precisares podes trabalha-la.
    - O objecto DataTable é basicamente uma cópia exacta da tua tabela do Acess/Sql/etc.. já formatada correctamente.
    - Usando a propriedade .DataSource, dás-lhe a Datatable e o proprio objecto (pelo nome julgo ser uma listbox) preenche-se automaticamente com os items da datatable.
    - Se quiseres podes ainda guardar os dados em cache tornando a DataTable Publica.
    - Permite-te ainda acesso as propriedades .DisplayMember e .Valuemember em caso de necessidade (se fores ver o que fazem deves perceber)
    - Se por alguma razão o teu programa bloquear/arrebentar, a ligação ao Sql nunca se mantêm aberta, evitando certos tipos de bloqueios (dependendo da configuração do SqlServer) que obrigam a reiniciar o server.

    Visto que és auto-didacta, aconselho-te a estudar bastante esta parte das datatables e ligações.
     
  7. H4LLoW

    H4LLoW Power Member

    Realmente assim as coisas fazem mais sentido!

    Em relação a esta opção, e desculpa a minha ignorancia, é que já por algumas vezes vi referência a
    ela mas continuo sem saber de que forma é que guardo os dados em cache?

    E já agora, muito obrigado pela dica e pela informação inerente a esta.
     
  8. PNDmartins

    PNDmartins Power Member

    Guardar os dados em Cache é um termo para manter os dados em memória, ou seja, por exemplo em vez disto:

    Código:
    Public sub Teste()
     
           Dim A as string = "Nome"
     
    End sub
    
    fazer isto:

    Código:
    [B]Public Class Form1[/B]
     
          Public A As String
     
          Public Sub Teste()
     
                 A = "Nome"
     
          End Sub
     
          Public Sub Teste2()
     
                 A = "Outro Nome"
     
          End Sub
    [B]End Class[/B]
    
    As diferenças são que todos os objectos que são declarados dentro de uma Sub/Function/etc... apenas existem dentro destas mesmas subs/functions/etc.. e ao sair das mesmas, os objectos são destruidos, mas ao declarar como públicas, e fora das subs (neste caso usei um form), enquanto o form estiver aberto a variavel A vai conter sempre o valor "Nome" ou o valor "Outro Nome" dependendo de qual das subs for chamada.

    Se em vez de declarar num form, fizer a declaração dentro de um modulo, é exactamente a mesma coisa com a excepção de que enquanto o programa estiver a correr, a variavel A ha-de ter sempre ou o valor "Nome" ou o valor "Outro Nome", dependo de que sub foi chamada.

    Isto já é manter os dados em cache, ou seja, em memória. Basicamente é manter uma certa informação acessivel a qualquer altura.

    Também se pode aplicar a tabelas de dados, listas, etc...

    Claro que nem sempre é a melhor maneira de solucionar um problema, mas é um caso a ponderar para bastantes situações, como por exemplo para o teu problema, para passar dados entre formulários, para criar niveis de acesso de utilizadores, etc..

    Espero que tenha sido esclarecedor
     
    Última edição: 25 de Maio de 2009
  9. H4LLoW

    H4LLoW Power Member

    Acho que já percebi!

    Se por exemplo, fizer um determinado form para efectuar o login de um utilizador, e após ele ser efectuado com sucesso quiser que o Nome e Apelido desse user seja mencionado em todos os forms abertos basta associar o nome e o apelido a uma determinada variável e através de um módulo, ou form, torná-la publica a toda a aplicação, certo?
     
  10. H4LLoW

    H4LLoW Power Member

    Substitui o código anterior pelo que me sugeriste, mas agora aparece:

    1º Sublinhado - 'ConnectionString' is not a member of System.Data.OleDb.OleDbCommand'
    2º Sublinhado - Value of type 'System.Data.OleDb.OleDbCommand' cannot be converted to 'System.Data.SqlClient.SqlCommand'

    As variáveis estavam declaradas desta forma, suponho que tenho de as alterar?

    Código:
    Public Class frmPrcr
        Dim [COLOR="Red"][U]cn[/U][/COLOR] As New System.Data.OleDb.OleDbConnection
        Dim [COLOR="Red"][U]cm[/U][/COLOR] As New System.Data.OleDb.OleDbCommand
        Dim rd As System.Data.OleDb.OleDbDataReader
    
    Código:
     cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=cntbl.mdb"
     [U][COLOR="Red"]cm.ConnectionString[/COLOR][/U] = cn
     cm.CommandText = "select * from tblfrnc where frnc_nm like '" & txtSrch.Text & "%'"
     
     Dim Adp as new SqlDataAdapter([U][COLOR="Red"]cm[/COLOR][/U])
     Dim Dt as new DataTable
     
     Adp.fill(Dt)
     
     lstfrnc.DataSource = Dt
    
     
  11. Thorak

    Thorak Power Member

    Não podes usar:

    Dim Adp as new SqlDataAdapter(cm) é uma classe usada em conexões com SQL Server

    tens que usar o

    Dim Adp as new OledbDataAdapter(cm)


    O PNDmartins esqueceu-se que estás a trabalhar em Access e não SQLServer quando escreveu o código
     
  12. Thorak

    Thorak Power Member

    Já agora, em resposta à utilização ou não de um datareader em vez de um dataadapter+datatable

    O datareader é a ferramenta preferencial para seleccionar dados da BD. Em que o objectivo seja somente ler e que não implique inserts updates ou deletes.

    É um objecto bastante mais simples e leve que um dataadapter que tem um grande conjunto de métodos que são desnecessários para quem quer somente seleccionar dados.

    OS dados são retornados assim que o query acabar de processar, mas guarda o resultado num buffer de rede no lado do cilente até que usamos o comando READ e portanto não se perde informação se houver um problema na rede.

    Para quem só quer listagens o Datareader é recomendável.
    Já agora, também há forma de fazer um fill de uma datatable através de um datareader

    DataReader


     
    Última edição: 26 de Maio de 2009
  13. H4LLoW

    H4LLoW Power Member

    Obrigado pela solução Thorak, consegui librar-me dos erros.
    Mas deixei de obter os resultados desejados na minha listbox agora só me aparece na lista System.Data.DataRowView

    Já agora voltando ao código do PNDmartins:

    Código:
    cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=cntbl.mdb"
    [U][COLOR="Red"] cm.ConnectionString = cn[/COLOR][/U] [COLOR="DarkGreen"]'Não será?[/COLOR] [COLOR="Navy"][B]cm.Connection = cn[/B][/COLOR]
     cm.CommandText = "select * from tblfrnc where frnc_nm like '" & txtSrch.Text & "%'"
     
     Dim Adp as new SqlDataAdapter(cm)
     Dim Dt as new DataTable
     
     Adp.fill(Dt)
     
     lstfrnc.DataSource = Dt
    Alterei para a sugestão apresentada no código mas obtenho o retorno obtido em cima.
     
    Última edição: 26 de Maio de 2009
  14. PNDmartins

    PNDmartins Power Member

    Boas

    Desde já peço desculpas nas alterações mas sim, enganei-me e em vez de sqlDataAdapter é OleDbDataAdapter como foi referido pelo Thorak.

    Em relação ao erro:

    Também tens razão e novamente, erro de código. Estou muito habituado ao Sql e certas coisas já saem automaticas.

    Em relação a explicação do Thorak em relação aos datareaders, obrigado pelo esclarecimento. Sempre me meteu uma confusão o porque de se ler directamente em vez de puxar os dados.
     
  15. PNDmartins

    PNDmartins Power Member

    em relação a este erro: System.Data.DataRowView experimenta isto:

    Código:
      ListBox1.DataSource = Dt
      ListBox1.DisplayMember = "Nome da coluna a ser apresentada na lista"
    
    este código já foi testado (desta vez não quis correr riscos :p) e funciona.
     
  16. H4LLoW

    H4LLoW Power Member

    Bem o código final para preencher a listbox já está a funcionar:

    Código:
    Private Sub txtSrch_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtSrch.TextChanged
            cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=cntbl.mdb"
            cm.Connection = cn
            cm.CommandText = "select * from tblfrnc where frnc_nm like '" & txtSrch.Text & "%'"
    
            Dim Adp As New OleDbDataAdapter(cm)
            Dim Dt As New DataTable
    
            Adp.fill(Dt)
    
            lstFrnc.DataSource = Dt
            lstFrnc.DisplayMember = "frnc_nm"
            lstFrnc.Refresh() '[COLOR="Yellow"]---> Tive de acrescentar esta ultima linha para apresentar os resultados.[/COLOR]
        End Sub
    Agora não me funciona o evento lstFrnc_SelectedIndexChanged

    Código:
    Private Sub lstFrnc_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles lstFrnc.SelectedIndexChanged
            ' obtem o nome selecionado no listbox
            txtNome.Text = lstFrnc.SelectedItem
        End Sub
    O erro que aparece é o seguinte:

    [​IMG]
     
  17. PNDmartins

    PNDmartins Power Member

    A listabox está a tratar todos os objectos como uma DataRow, e não consegue obter os dados directamente. Experimenta alterar a propriedade .SelectedItem para .Text

    Código:
    txtNome.Text = lstFrnc[B].Text[/B]
    
     
  18. H4LLoW

    H4LLoW Power Member

    Assim já tenho a textbox e a listbox a funcionar!

    Agora vou continuar a procurar a forma de preencher as outras textboxs.

    Obrigado a todos pela ajuda.
     

Partilhar esta Página