Synchronize items in comboboxes at run time

1

I've tried for some time to figure out how to synchronize one combobox with another. I am wanting to sync comboboxes at runtime. When the user selects a category in the combobox, depending on their choice, the combobox subcategory will display the subcategories of the selected category.

I'm using WPF and C # with EntityFramework 6.

In my application, I can read in my ViewModel what was selected in the comboBox in View. I would like to know how do I dynamically update a combobox by ordering from what was selected in another combobox using the MVVM standard. Here are excerpts from the code:

<ComboBox Name="cbCategoria" 
          ItemsSource="{Binding NomeCategorias}" 
          SelectedItem="{Binding NomeCategoria}"
          Width="175" />


<ComboBox Name="cbSubCtg" 
          ItemsSource="{Binding NomeSubCategorias}" 
          SelectedItem="{Binding NomeSubCategoria}"
          Width="175" />

As you can see, there in my ViewModel I save what I read in ComoboBox cbCategoria in variable NomeCategoria .

Thanks in advance for any help.

    
asked by anonymous 17.11.2015 / 23:22

2 answers

2

I was able to solve my problem! I used the SelectedChanged event in the ComboBox that "commands" in the second. I am now able to dynamically update the second ComboBox. Here is the code:

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;                        
        }

I know you still need some tweaking, but this example will give insight to other members of this community. I hope someone contributed with anything, it can still improve.

    
18.11.2015 / 02:18
1

I do it another way. I make a Binding of the second ComboBox in the first. Assume that the ItemsSource of the first combo is List<Categorias> and each item in that list has a List<SubCategorias>

The classes would be like this

public class Categoria 
{
   public int CodigoCategoria { get; set; }
   public string NomeCategoria { get; set; }
   public ICollection<SubCategoria> SubCategorias { get; set; }
}

public class SubCategoria 
{
   public int CodigoSubCategoria { get; set; }
   public int CodigoCategoria { get; set; }
   public string NomeSubCategoria { get; set; }
}

Binding would look like this:

<ComboBox x:Name="cboGrupo" 
          SelectedValue="{Binding CodigoCategoria, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
          SelectedValuePath="CodigoCategoria" 
          DisplayMemberPath="NomeCategoria" />


<ComboBox x:Name="cboSubGrupo"
          ItemsSource="{Binding ElementName=cboGrupo, Path=SelectedItem.SubCategorias, Mode=TwoWay}"
          SelectedValue="{Binding CodigoSubGrupo, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
          SelectedValuePath="CodigoSubCategoria" 
          DisplayMemberPath="NomeSubCategoria" />

You need to load the first ComboBox . Here's an example with EntityFramework.

public void Carregar(){
  // selecionar as categorias no banco incluindo as subcategorias
  List<Categorias> categorias = db.Categorias
                                  .Include(cat => cat.SubCategorias)
                                  .ToList();
  cboGrupo.ItemsSource = categorias;
}

In this way, changing a category in the first ComboBox automatically changes the subcategories.

    
18.11.2015 / 20:55