none
Sincronizar ComboBoxes em tempo de Execução RRS feed

  • Pergunta

  • Estou querendo sincronizar comboboxes em tempo de execução. Quando o usuário selecionar uma categoria na combobox, dependendo da sua escolha, a combobox subcategoria irá mostrar as subcategorias da categoria selecionada.

    Estou usando WPF e C# com EntityFramework 6.

    Desde já agradeço qualquer ajuda.

    terça-feira, 17 de novembro de 2015 21:57

Respostas

  • Consegui resolver meu problema! Usei o evento SelectedChanged na ComboBox que "comanda" na segunda. Agora estou conseguindo atualizar dinamicamente a segunda ComboBox. Segue o código:

    private void cbCategoria_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                var cbCategoria = sender as ComboBox;
                int ctgId = -1;
                string temp = string.Empty;
                ObservableCollection<string> listaCtg;
    
                nomeCtg = cbCategoria.SelectedItem as string;
                Debug.WriteLine($"Sub categoria lida no handler {nomeCtg}");
    
                using (DataContext db = new DataContext())
                {
                    // Procura o nome da categoria selecionada na ComboBox
                    var categoria = from x in db.Categorias
                                    where x.CategoriaNome.Equals(nomeCtg)
                                    select x;
    
                    foreach (var p in categoria) { ctgId = p.CategoriaId; }
    
                    // Procura o Id correspondente com a das categorias
                    var subCtg = from x in db.SubCategorias
                                 where x.Categoria.CategoriaId == ctgId
                                 select x;
    
                   listaCtg = new ObservableCollection<string>();
    
                    foreach (var p in subCtg)
                    {
                        temp = p.SubCtgNome;
                        listaCtg.Add(temp);
                        Debug.WriteLine($"Subcategoria aaaa {temp}");
                    }
                }
    
                cbSubCtg.ItemsSource = listaCtg;                        
            }

    Sei que ainda precisa de alguns ajustes, mas este exemplo dará idéia para outros membros desta comunidade. Espero que alguém contribuia com qualquer coisa, ainda dá para melhorar.

    • Marcado como Resposta Iago Frota quarta-feira, 18 de novembro de 2015 01:23
    quarta-feira, 18 de novembro de 2015 01:22

Todas as Respostas

  • Boa noite.

    Tu podes usar o evento "SelectionChanged" para executar uma ação ao mudar o item selecionado de um ComboBox.

    No teu caso tu farias o seguinte: ao disparar o evento tu pegarias o Id da categoria selecionada, pegaria a lista de sub-categorias desta categoria (do banco de dados, possivelmente) e jogaria no ComboBox das subcategorias.


    Att., Rafael Simor

    terça-feira, 17 de novembro de 2015 22:08
  • Boa noite.

    Tu podes usar o evento "SelectionChanged" para executar uma ação ao mudar o item selecionado de um ComboBox.

    No teu caso tu farias o seguinte: ao disparar o evento tu pegarias o Id da categoria selecionada, pegaria a lista de sub-categorias desta categoria (do banco de dados, possivelmente) e jogaria no ComboBox das subcategorias.


    Att., Rafael Simor

    Rafael, desde de já lhe agradeço.

    Eu estava usando o tutorial deste http://www.dotnetperls.com/combobox-wpf para tentar fazer algo em meus estudos, mas não obtive success. Se possível, você poderia colocar um exemplo, acredito que será útil não só para mim, mas para a comunidade.


    terça-feira, 17 de novembro de 2015 22:21
  • Iago, acredito que ISTO seja útil pra ti.

    A questão é:

    Tu precisas mostrar o texto da categoria, porém precisas também manter o valor da chave primária dela no mesmo item. Com o SelectionChanged tu pegas o ID da categoria selecionada, gera a lista de sub-categorias e preenche seu outro ComboBox.


    Att., Rafael Simor

    terça-feira, 17 de novembro de 2015 22:47
  • Iago, o que vc esta procurando é mais ou menos isso ?

    ComboBoxFabricantes    

    ComboBoxModelos 

     public void carregafabricante()
            {  try
                {
                    con = new SqlConnection(acesso11);
                    string strSql = "SELECT * FROM Tbl_Fabricante";
                    con = new SqlConnection(acesso11);
                    cmd = new SqlCommand(strSql, con);
                    con.Open();
                    cmd.CommandType = CommandType.Text;
                    SqlDataAdapter da4 = new SqlDataAdapter(cmd);
                    DataTable fabri = new DataTable();
                    da4.Fill(fabri);
                    this.cbFabricante.DataSource = fabri;
                    this.cbFabricante.DisplayMember = "NomeFabricante";
                    this.cbFabricante.ValueMember = "id_fabricante";
                   
                    con.Close();
                }
                catch (Exception ex)
                { MessageBox.Show("Erro: " + ex.Message); }
            }
    
    
    private void carregamodelo()
            {   try
                    {
                        int idfm = fab;
                        lblidfabri.Text = idfm.ToString();
                        con = new SqlConnection(acesso11);
                        string strSql = ("Select * from Tbl_ModeloAeronave where Tbl_ModeloAeronave.ID_FABRICANTE like '" + idfm + "%'");
                        con = new SqlConnection(acesso11);
                        cmd = new SqlCommand(strSql, con);
                        cmd.Parameters.AddWithValue("@dthji", idfm);
                        con.Open();
                        cmd.CommandType = CommandType.Text;
                        SqlDataAdapter da1 = new SqlDataAdapter(cmd);
                        DataTable mode = new DataTable();
                        da1.Fill(mode);
                        this.cbModelo.DataSource = mode;
                        this.cbModelo.DisplayMember = "Modelo";
                        this.cbModelo.ValueMember = "id_ModAero";
                        con.Close();
                    }
                    catch (Exception ex)
                    { MessageBox.Show("Erro: " + ex.Message); }
            }
    
    // Combofabricantes eventos Leave / Validating / Click
    
     private void cbFabricante_Leave(object sender, EventArgs e)
            {
                fab = int.Parse(cbFabricante.SelectedValue.ToString());
            }
    
            private void cbFabricante_Validating(object sender, CancelEventArgs e)
            {      
                carregamodelo();
            }
    
            private void cbFabricante_Click(object sender, EventArgs e)
            {
                cbModelo.SelectedIndex = -1;
            }
    
    
    
    
    
    
    
    
    
    
    
    


    Em resumo no load do teu form vc vai inserir 

     carregamodelo(); // carrega os modelos 
      cbModelo.SelectedIndex = -1; // deixo o combo sem mostrar nada 
     cbFabricante.SelectedIndex = -1; // e o combo de fabricantes tambem.

    No leave do combo fabricante passo uma variavel fab,  quando realizo o validating do combobox chamo a função carregamodelo que recebe a variavel fab como paramentro da consulta. e pronto carrega no combo modelo os modelos vinculados aquele fabricante.

    Não alterei os nomes mas fica facil vc adaptar a tua necessidade. 

    Espero que te ajude. 

    Att, wsti.

     
    terça-feira, 17 de novembro de 2015 22:47
  • Iago, o que vc esta procurando é mais ou menos isso ?

    ComboBoxFabricantes    

    ComboBoxModelos 

     public void carregafabricante()
            {  try
                {
                    con = new SqlConnection(acesso11);
                    string strSql = "SELECT * FROM Tbl_Fabricante";
                    con = new SqlConnection(acesso11);
                    cmd = new SqlCommand(strSql, con);
                    con.Open();
                    cmd.CommandType = CommandType.Text;
                    SqlDataAdapter da4 = new SqlDataAdapter(cmd);
                    DataTable fabri = new DataTable();
                    da4.Fill(fabri);
                    this.cbFabricante.DataSource = fabri;
                    this.cbFabricante.DisplayMember = "NomeFabricante";
                    this.cbFabricante.ValueMember = "id_fabricante";
                   
                    con.Close();
                }
                catch (Exception ex)
                { MessageBox.Show("Erro: " + ex.Message); }
            }
    
    
    private void carregamodelo()
            {   try
                    {
                        int idfm = fab;
                        lblidfabri.Text = idfm.ToString();
                        con = new SqlConnection(acesso11);
                        string strSql = ("Select * from Tbl_ModeloAeronave where Tbl_ModeloAeronave.ID_FABRICANTE like '" + idfm + "%'");
                        con = new SqlConnection(acesso11);
                        cmd = new SqlCommand(strSql, con);
                        cmd.Parameters.AddWithValue("@dthji", idfm);
                        con.Open();
                        cmd.CommandType = CommandType.Text;
                        SqlDataAdapter da1 = new SqlDataAdapter(cmd);
                        DataTable mode = new DataTable();
                        da1.Fill(mode);
                        this.cbModelo.DataSource = mode;
                        this.cbModelo.DisplayMember = "Modelo";
                        this.cbModelo.ValueMember = "id_ModAero";
                        con.Close();
                    }
                    catch (Exception ex)
                    { MessageBox.Show("Erro: " + ex.Message); }
            }
    
    // Combofabricantes eventos Leave / Validating / Click
    
     private void cbFabricante_Leave(object sender, EventArgs e)
            {
                fab = int.Parse(cbFabricante.SelectedValue.ToString());
            }
    
            private void cbFabricante_Validating(object sender, CancelEventArgs e)
            {      
                carregamodelo();
            }
    
            private void cbFabricante_Click(object sender, EventArgs e)
            {
                cbModelo.SelectedIndex = -1;
            }
    
    
    
    
    
    
    
    
    
    
    


    Em resumo no load do teu form vc vai inserir 

     carregamodelo(); // carrega os modelos 
      cbModelo.SelectedIndex = -1; // deixo o combo sem mostrar nada 
     cbFabricante.SelectedIndex = -1; // e o combo de fabricantes tambem.

    No leave do combo fabricante passo uma variavel fab,  quando realizo o validating do combobox chamo a função carregamodelo que recebe a variavel fab como paramentro da consulta. e pronto carrega no combo modelo os modelos vinculados aquele fabricante.

    Não alterei os nomes mas fica facil vc adaptar a tua necessidade. 

    Espero que te ajude. 

    Att, wsti.

     
    Eu tinha tentado, agora há pouco, mais ou menos assim. Esta sua solução não está usando o padrão MVVM. Se pudesse, você poderia colocar um exemplo utilizando MVVM?
    terça-feira, 17 de novembro de 2015 23:11
  • Iago, acredito que ISTO seja útil pra ti.

    A questão é:

    Tu precisas mostrar o texto da categoria, porém precisas também manter o valor da chave primária dela no mesmo item. Com o SelectionChanged tu pegas o ID da categoria selecionada, gera a lista de sub-categorias e preenche seu outro ComboBox.


    Att., Rafael Simor

    Rafael, fiz um exemplo, mais ou menos igual ao que vc me passou, mas vi que não estou obedecendo o padrão MVVM. Na minha aplicação, eu consigo ler na minha ViewModel o que foi selecionado na comboBox na View. Queria saber como faço para atualizar, dinamicamente,  uma combobox depedendo do que foi selecionado em uma outra combobox, utilizando o padrão MVVM.
    • Editado Iago Frota terça-feira, 17 de novembro de 2015 23:17 melhor entendimento
    terça-feira, 17 de novembro de 2015 23:15
  • Consegui resolver meu problema! Usei o evento SelectedChanged na ComboBox que "comanda" na segunda. Agora estou conseguindo atualizar dinamicamente a segunda ComboBox. Segue o código:

    private void cbCategoria_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                var cbCategoria = sender as ComboBox;
                int ctgId = -1;
                string temp = string.Empty;
                ObservableCollection<string> listaCtg;
    
                nomeCtg = cbCategoria.SelectedItem as string;
                Debug.WriteLine($"Sub categoria lida no handler {nomeCtg}");
    
                using (DataContext db = new DataContext())
                {
                    // Procura o nome da categoria selecionada na ComboBox
                    var categoria = from x in db.Categorias
                                    where x.CategoriaNome.Equals(nomeCtg)
                                    select x;
    
                    foreach (var p in categoria) { ctgId = p.CategoriaId; }
    
                    // Procura o Id correspondente com a das categorias
                    var subCtg = from x in db.SubCategorias
                                 where x.Categoria.CategoriaId == ctgId
                                 select x;
    
                   listaCtg = new ObservableCollection<string>();
    
                    foreach (var p in subCtg)
                    {
                        temp = p.SubCtgNome;
                        listaCtg.Add(temp);
                        Debug.WriteLine($"Subcategoria aaaa {temp}");
                    }
                }
    
                cbSubCtg.ItemsSource = listaCtg;                        
            }

    Sei que ainda precisa de alguns ajustes, mas este exemplo dará idéia para outros membros desta comunidade. Espero que alguém contribuia com qualquer coisa, ainda dá para melhorar.

    • Marcado como Resposta Iago Frota quarta-feira, 18 de novembro de 2015 01:23
    quarta-feira, 18 de novembro de 2015 01:22
  • Iago, isto foi exatamente o que eu e o Wsti te falamos:

    Evento SelectedChanged na combobox > pega ID > busca sub-categorias > joga na ComboBox de sub-categorias.

    Uma melhoria:

    No lugar de uma Lista de string, coloque o ItemsSource como uma lista do objeto que tu pretendes mostrar (Categoria e SubCategoria).

    Assim tu podes pegar, por exemplo, o ID da Categoria sem precisar buscar no banco de dados pelo nome (caso tenha uma categoria com nome igual, por exemplo, ele sempre irá pegar a primeira cadastrada).

    Para fazer isso, volto a mencionar o link que postei anteriormente; tu podes utilizar a propriedade SelectedItem ou SelectedValue, dependendo da maneira que tu irás construir tua lógica.


    Att., Rafael Simor

    quarta-feira, 18 de novembro de 2015 01:39