PROBLEMAS COM COMBOBOX

LUIS.HERRERA 11/02/2015 11:13:27
#444458
Felipe uso C#, mas o conceito vai ser o mesmo.
ao usar Combo não recomento usar a propriedade Text para passar dados, pois na realidade você está associando um ID + Texto do banco ao controle, sendo que ele usa internamente um Index do combo para localização dos dados carregados. Quando trabalho com combo só uso o ID do dado e mando ele exibir o texto. para facilitar tudo criei um método público para localizar um item dentro de qualquer combo, passando o próprio combo e ID para localizar é uma mão na roda, fica assim:

Minha classe pública fica numa DLL incorporada ao projeto principal assim:
public static void CarregaCombo(ComboBox myCbo, string mySituacao, int myID) //-> myID é necessário apenas para informar uma Empresa Específica)
{
switch (myCbo.Name)
{
case [Ô]cboInformatica[Ô]:
InformaticaBLL objInformatica = new InformaticaBLL();
myCbo.DisplayMember = [Ô]Software[Ô];
myCbo.ValueMember = [Ô]IDSoftware[Ô];
myCbo.DataSource = objInformatica.CarregaCombo(myID, mySituacao);
myCbo.SelectedIndex = -1;
myCbo.Refresh();
break;
case [Ô]cboCargos[Ô]:
CargoBLL objCargo = new CargoBLL();
myCbo.DisplayMember = [Ô]NOME[Ô];
myCbo.ValueMember = [Ô]IDCargo[Ô];
myCbo.DataSource = objCargo.CarregaCombo(myID, mySituacao);
myCbo.SelectedIndex = -1;
myCbo.Refresh();
break;
// etc.....
}
}

public static void LocalizaItemCombo(ComboBox myCbo, int myID)
{
//-> aqui percorro o List do DataSource associado ao combo, para identificar o item com mesmo ID e setar o combo nele
switch (myCbo.Name)
{
case [Ô]cboInformatica[Ô]:
foreach (InformaticaModelo info in myCbo.Items)
{
if (info.IDSoftware == myID)
{
myCbo.SelectedItem = info; //achou item então seleciona ele
return;
}
else
{
myCbo.SelectedIndex = -1; // não achou então não seleciona nenhum index = -1
}
}
break;
// etc....
}
}


Load do form carrega os combos
ClasseAcoesForms.CarregaCombo(cboInformatica, [Ô]Ativos[Ô], VariaveisAmbiente.ParametroNaoUsado.Zero); 


Ao clicar num grid uso o seguinte código
ClasseAcoesForms.LocalizaItemCombo(cboInformatica, Convert.ToInt32(gridInformatica.CurrentRow.Cells[[Ô]IDSoftware[Ô]].Value.ToString()));   


Pronto assim fica tudo automatizado, reaproveita código, reduz trabalho e o item é localizado pelo ID, pois se houver alteração no texto de um registro (edição) e tentar localizar por ele não o encontrará. Pelo ID isso nunca acontece.
FELLIPEASSIS 11/02/2015 22:30:14
#444464
Só não entendi a parte onde localiza o item para aparecer no combobox.
essa aqui
ClasseAcoesForms.CarregaCombo(cboInformatica, [Ô]Ativos[Ô], [txt-color=#e80000]VariaveisAmbiente.ParametroNaoUsado.Zero[/txt-color]);

foreach ([txt-color=#e80000]InformaticaModelo[/txt-color] info in myCbo.Items)
{
if (info.[txt-color=#e80000]IDSoftware[/txt-color] == myID)
{
myCbo.SelectedItem = info; //achou item então seleciona ele
return;
}
else
{
myCbo.SelectedIndex = -1; // não achou então não seleciona nenhum index = -1
}
}
as partes de vermelho foi as que fiquei mais em duvida, sou novo em matéria de programação
NICKOSOFT 12/02/2015 06:49:11
#444465
em vb
  
Public Sub LocalizaItemCombo(ByVal myCBO As ComboBox, ByVal myID As Integer)
Select Case myCBO.Name
Case [Ô]ComboBox1[Ô] [ô]seu nome do combo
For Each info As DataRowView In myCBO.Items
If info.Item([Ô]cep[Ô]) = myID Then [ô]item tem q ser o id ou campo atrelado ao valuemember
myCBO.SelectedItem = info
End If
Next
End Select
End Sub


uma rotina simples de preencher combo q vc pode adaptar incluindo o combo a ser preenchido e passando a consulta
  
Dim con = New OleDbConnection([Ô]Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\cep2014.MDB[Ô])
con.Open()

Dim sql As String = [Ô]select log_nome,cep,ufe_sg FROM log_logradouro where ufe_sg=[ô]AC[ô][Ô]
Dim CD As New OleDbCommand()
CD.Connection = con
CD.CommandText = sql
CD.ExecuteNonQuery()

With dtAdapter
.SelectCommand = CD
.Fill(dsDataSet)
End With
ComboBox1.DisplayMember = [Ô]log_nome[Ô]
ComboBox1.ValueMember = [Ô]cep[Ô]
ComboBox1.DataSource = dsDataSet.Tables(0)
ComboBox1.SelectedIndex = -1

em vez da query estar ali dentro vc envia como parâmetro, assim como o combo de destino e dados do connection....(pode ter certeza qnd o projeto crescer vai te ajudar muito essas mudanças.....aqui criei 2 telinhas so pra teste, imagina vc ter 200 telas e ir uma a uma alterando todas as chamadas ao banco de dados.....qnt mais rotinas vc criar desassociada a uma tela, mais genéricas elas forem melhor sera seu projeto....passando todos os parâmetros possíveis, vc cria uma rotina q usa em todas as telas do seu projeto, reduz linhas e esforço no momento de alterações....


achei muito show, e pratica dessa forma, vou estar usando assim agora nos projetos...
NICKOSOFT 12/02/2015 07:14:10
#444466
veja isso, pense numa classe
  
Imports System.Data.OleDb

Public Class Class1

Public Function Conecta() As OleDbConnection
Dim con = New OleDbConnection([Ô]Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\cep2014.MDB[Ô])
con.Open()
Return con
End Function

Public Sub LocalizaItemCombo(ByVal myCBO As ComboBox, ByVal myID As Integer, ByVal item As String)
Select Case myCBO.Name
Case [Ô]ComboBox1[Ô]
For Each info As DataRowView In myCBO.Items
If info.Item(item) = myID Then
myCBO.SelectedItem = info
End If
Next
End Select
End Sub

Public Sub PreencheCombo(ByVal myCBO As ComboBox, ByVal Query As String, ByVal VM As String, ByVal DM As String)
Dim con As OleDbConnection = Conecta()

Dim sql As String = Query
Dim CD As New OleDbCommand()

Dim dtAdapter As New OleDbDataAdapter
Dim dsDataSet As New DataSet

CD.Connection = con
CD.CommandText = sql
CD.ExecuteNonQuery()

With dtAdapter
.SelectCommand = CD
.Fill(dsDataSet)
End With

myCBO.DisplayMember = DM
myCBO.ValueMember = VM
myCBO.DataSource = dsDataSet.Tables(0)
myCBO.SelectedIndex = -1
myCBO.Refresh()
End Sub
End Class


pense no seu form onde esta o grid
  
Private Sub DataGridView1_CellDoubleClick(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellDoubleClick
Dim tela As New Form2
tela.Show()
Dim busca As New Class1
busca.LocalizaItemCombo(tela.ComboBox1, CInt(DataGridView1.CurrentRow.Cells([Ô]cep[Ô]).Value.ToString), [Ô]CEP[Ô]) [ô]vc ta enviando dados do combo q sofre acao, no caso o valor a buscar, e o nome do campo desse valor
End Sub

e o form onde o combo esta
  
Public Class Form2

Private Sub Form2_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim enche As New Class1
enche.PreencheCombo(Me.ComboBox1, [Ô]select log_nome,cep,ufe_sg FROM log_logradouro where ufe_sg=[ô]AC[ô][Ô], [Ô]CEP[Ô], [Ô]log_nome[Ô])[ô]vc passa tudo q precisa pro combo ser preenchido corretamente, o combo, a query, o valuemember e o displaymember, viu como tornou completamente livre pra ser usado em qq tela e combo do projeto
End Sub
End Class
LUIS.HERRERA 12/02/2015 09:25:40
#444470
Citação:

:
Só não entendi a parte onde localiza o item para aparecer no combobox.
essa aqui
ClasseAcoesForms.CarregaCombo(cboInformatica, [Ô]Ativos[Ô], [txt-color=#e80000]VariaveisAmbiente.ParametroNaoUsado.Zero[/txt-color]);

foreach ([txt-color=#e80000]InformaticaModelo[/txt-color] info in myCbo.Items)
{
if (info.[txt-color=#e80000]IDSoftware[/txt-color] == myID)
{
myCbo.SelectedItem = info; //achou item então seleciona ele
return;
}
else
{
myCbo.SelectedIndex = -1; // não achou então não seleciona nenhum index = -1
}
}
as partes de vermelho foi as que fiquei mais em duvida, sou novo em matéria de programação



Felipe é o seguinte, meu projeto é em 4 camadas (UI, negócios BLL, Dados DAL e Entidade Modelo.

O método
ClasseAcoesForms.CarregaCombo(cboInformatica, [Ô]Ativos[Ô], VariaveisAmbiente.ParametroNaoUsado.Zero);
que está na DLL, usa os parâmetros:
cboInformatica = nome do objeto combo a ser carregado
[Ô]Ativos[Ô] = string para carregar só os ativos, no meu caso pode ser ainda [Ô]Inativos[Ô] ou [Ô]Todos[Ô] (ambos). Isso porque nenhum registro em meu sistema é excluído, apenas inativas se não for mais utilizado, por rastreabilidade.
VariaveisAmbiente.ParametroNaoUsado.Zero = é uma structure para documentação dos valores, este parâmetro é o ID da empresa, quando os dados forem agrupados por unidades de negócio, filiais por exemplo. Se não for usa 0. Sendo assim usei essa variável da Structure para documentação apenas e não um simples 0.

Nota: esses parâmetros são por necessidade do meu projeto e não precisam existir, só o nome do combo mesmo.

Já o objeto InformaticaModelo é uma entidade usada para receber os dados, uma classe modelo com todos os campos necessários dessa camada Entidade, que corresponde a estrutura do banco, entendeu?

FFCOUTO 12/02/2015 09:36:14
#444471
Resposta escolhida
Amigos,

Na minha opinião o local mais indicado para carregar estas listas de opções (ComboBox, ListBox, etc) é no construtor do Form e não no Evento Load.
Usem um List<T> como datasource e basta setar o item na propriedade SelectedItem e pronto.

Um exemplo (em C#, é só adaptar para VB)

public class Opcao
{
public Opcao(int id, string texto)
{
this.ID = id;
this.Texto = texto;
}

public int ID { get; private set; }

public string Text { get; private set; }

public override bool Equals(object obj)
{
if ((obj == null) || !(obj is Opcao))
return false;
else
return this.ID == ((Opcao)obj).ID;
}

public override int GetHashCode()
{
return this.ID;
}
}


Cria as opções numa lista genérica
List<MyClass> listaOpcoes = new List<MyClass>();
listaOpcoes.Add(new MyClass(1, [Ô]opção 1[Ô]));
listaOpcoes.Add(new MyClass(2, [Ô]opção 2[Ô]));
listaOpcoes.Add(new MyClass(3, [Ô]opção 3[Ô]));


Altere o construtor do form
public SeuForm(List<Opcao> opcoes)
{
InitializeComponent();

// aqui você preenche a lista
comboBox1.Items.AddRange(opcoes.ToArray());
}

public void SelecionaOpecao(Opcao minhaOpcao)
{
comboBox1.SelectedItem = minhaOpcao;
}


Para chamar o Form e selecionar uma opção
var wnd = new SeuForm(listaOpcoes);
wnd.SelecionaOpcao(listaOpcoes[0]); // lembre-se que o índice começa em zero
wnd.Show(); // Pode-se usar também ShowDialog();


Caso você queira deixar a lista sem seleção basta passar um null no parâmetro
wnd.SelecionaOpcao(null);


Pronto acho que é isso.
NICKOSOFT 12/02/2015 20:31:59
#444485
este trecho de código q postei primeiro é a tradução mais simples do código do LH
  
Public Sub LocalizaItemCombo(ByVal myCBO As ComboBox, ByVal myID As Integer)
Select Case myCBO.Name
Case [Ô]ComboBox1[Ô] [ô]seu nome do combo
For Each info As DataRowView In myCBO.Items
If info.Item([Ô]cep[Ô]) = myID Then [ô]item tem q ser o id ou campo atrelado ao valuemember
myCBO.SelectedItem = info
End If
Next
End Select
End Sub

se o problema estava so em entender algumas coisas, creio ter ficado muito simples e totalmente funcional....
FELLIPEASSIS 12/02/2015 21:48:53
#444486
infelizmente meus amigos, está dando errado, sou novato em vb.net.
o erro é não pode converter string para inteiro.
daí mudei e não passou nada para o form de cadastro, não sei oque fazer mais
apenas queria que passasse o texto da coluna do datagridview para o combobox do form cadastro
ficou assim

Public Sub LocalizaItemCombo(ByVal myCBO As ComboBox, ByVal myID As Integer, ByVal item As String)
Select Case myCBO.Name
Case [Ô]cmbModelo[Ô]
For Each info As DataRowView In myCBO.Items
If info.Item([Ô]nome[Ô]) = myID Then [ô]item tem q ser o id ou campo atrelado ao valuemember
myCBO.SelectedItem = info
End If
Next
Case [Ô]cmbLocalidade[Ô]
For Each info As DataRowView In myCBO.Items
If info.Item([Ô]nome[Ô]) = myID Then [ô]item tem q ser o id ou campo atrelado ao valuemember
myCBO.SelectedItem = info
End If
Next
End Select
End Sub
no form de consulta ficou assim
Dim cls As New Cls_Combo
cls.LocalizaItemCombo(Frm_Cad_Equip.cmbModelo, CInt(dgvPesquisa.CurrentRow.Cells([Ô]nome[Ô]).Value.ToString), [Ô]nome[Ô])
mais dá erro, ha algo de errado? desculpem ser chato, mais é porque estou aprendendo.
OMAR2011 12/02/2015 23:23:04
#444488
FELLIPEASSIS, o melhor jeito para corrigir este erro seu é colocar seu projeto para o pessoal baixar e te mostra onde está
acontecendo este erro.
Adiciona seu projeto.
NICKOSOFT 13/02/2015 06:21:45
#444489
Imagino q o erro seja aki Item.info([Ô]nome[Ô])
Vc tem q usar o campo do id o campo numerico, se vc preenche seu combo c display nome e valuemember id, o info tem q apontar ao id, veja o comentario q deixei, campo atrelado ao valuemember do combo
O display do combo é o q aparece para nos, o value em geral seria um identificador unico no banco de dados, um valor invisivel ao usuario, pra clarear, pense numa tabela de produtos, nada impede q vc tenha mais de um produto c o mesmo nome (display), porem o campo identificador (value) sera diferente pra todos, m campo q nunca se repete, entra na questao do banco de dados trabalhar c chaves primarias identidade essas coisas....

Se ficou confuso posta o codigo q preenche o combo, e se realmente o erro esta na linha q comentei q o pessoal da uma força

veja na parte q preenche o combo q postei
  
ComboBox1.DisplayMember = [Ô]log_nome[Ô]
ComboBox1.ValueMember = [Ô]cep[Ô]
ComboBox1.DataSource = dsDataSet.Tables(0)
ComboBox1.SelectedIndex = -1

minha tabela é de ceps e endereços, então sabemos q cep seria um campo único q não repete, por isso na hora da pesquisa uso o cep, o cep é o valor passado do outro form onde tem o grid, por isso meu item.info([Ô]cep[Ô])= a variável q veio do outro form
experimente usar break points pra entender, pra ver o q esta sendo lido nas variáveis, ajuda muito, as vezes até colocar messagebox com a variável pra vc ver o q esta sendo realmente trabalhado...

reparando vi mais coisas
cls.LocalizaItemCombo(Frm_Cad_Equip.cmbModelo, CInt(dgvPesquisa.CurrentRow.Cells([Ô]nome[Ô]).Value.ToString), [Ô]nome[Ô])
veja o q esta acontecendo, vc esta pegando a linha atual, tentando converter o conteúdo da linha x coluna(nome), essa coluna por acaso tem um texto(string)? não tem como vc fazer a conversão de texto para inteiro, q é o q o comando cint tenta, aponte para coluna do código único do produto, e aponte novamente para esse campo na rotina de pesquisa no combo....

eu vi vc enviar o nome como ultimo parâmetro pra função, mas da forma q usou a função Item.info([Ô]nome[Ô]) vc já apontou o item dentro de parentes, então não existe a necessidade do mesmo nem na função, nem na hora de chama-la, vc passou o parâmetro, mas ele não foi usado.....

Página 2 de 3 [26 registro(s)]
Tópico encerrado , respostas não são mais permitidas