Sync items in comboboxes at runtime

Asked

Viewed 473 times

1

I’ve been trying to figure out how to synchronize a combobox with another one for some time. I’m looking to synchronize comboboxes at runtime. When the user selects a category in the combobox, depending on his choice, the combobox subcategory will show the subcategories of the selected category.

I am 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 wanted to know how to update, dynamically, a combobox depeded from what was selected in another combobox, using the MVVM standard. Follow 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, in my Viewmodel I keep what I read in Comobobox cbCategoria in the variable NomeCategoria.

From now on I appreciate any help.

  • I’m using this site to get an idea (http://www.dotnetperls.com/combobox-wpf), but I’m not sure how to get what was read on the first combobox .

  • 1

    It’s been a while since I’ve worked with WPF, you’ve tried to use the event SelectionChanged combo? I’m writing an answer that uses it, but I don’t know if that’s your problem.

  • @jbueno I even got an example saying this, but I think it doesn’t look cool, because, in my head, I’ll have to put logic in the Behind code of the view. I think the solution to my problem will use yes the SelectionChanged, but it won’t be just that. I think... rsrsrs

  • My problem is being on how to update this at runtime.

2 answers

2


I managed to solve my problem! I used the event SelectedChanged in the Combobox that "commands" in the second. Now I am able to dynamically update the second Combobox. Follow 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 it still needs some tweaking, but this example will give some idea to other members of this community. I hope someone will contribute something, can still improve.

1

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

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 be 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. Follow 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;
}

Thus, by changing a category in the first ComboBox, automatically change the subcategories.

  • I really liked your approach, it seems that you are closer to MVVM! I will use in my application. Thank you very much!

  • I tried to use in my application but did not understand much how it works. You could explain better?

  • 1

    I changed the answer. I make a Itemssource check of the second combo in the first combo, for the property Selecteditem. This property is a Category object, and this object has a list of Subcategories. Since the mode of this Binding is Twoway, when you change an item in the first combo, you already update the Itemssource of the second. Include or Join must be added to the query.

  • Interesting. I was wondering if the method public void Carregar() is on Viewmodel or is on Codebehind?

  • He is in the Behind of View because he needs to access the combobox, but if he wanted to leave in Viewmodel, the Itemssource of the first group would be a Binding for his Viewmodel collection. The two forms work.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.