0

Scenario

ComboBox C depends on the selected value of ComboBox B, which depends on the selected value of ComboBox A. All of these ComboBoxes are in a DataGrid.

Common Road Blocks:

  1. The User must be able to add new rows (This Requires a ItemsSource item type that has a parameterless constructor).
  2. To access the database to populate the List of Available Options for the Comboboxes, the current project would require the Database Credentials/DataContext be passed into the Constructor.

Attempt 1

I've tried using 3 CollectionViewSources, one for each of the ComboBoxes (Concept Code Here), but the SelectedItem of the ComboBox gets automatically selected in the other DataGrid rows. I need to find a way to isolate the CollectionViewSource to each row.

I've considered just adding the CollectionViewSource data to each of the DataGrid Items so I can just bind to it that way, but I have to access the database to generate the CollectionViewSource.

I also tried not sharing the CollectionViewSource as seen in this question, but that destroyed the link between the 3 ComboBoxes, as well as the Rows. If I could just set the CollectionViewSources to be shared within each DataGrid Row and not between each of them, I think it would work. I just can't find a way to do that.

Attempt 2

I've looked at this question: How to get cell level ComboBox for WPF DataGrid?

This would work, but the User needs to be able to add rows to the DataGrid. The example code in that question also uses a parameterless constructor. I am in a situation where access to the database to populate the lists would have to be passed into the constructor.

The Question

How do I do this correctly?

Community
  • 1
  • 1
Paxenos
  • 2,756
  • 4
  • 21
  • 20

1 Answers1

1

Bind to a List or ObservableCollection, not a CollectionViewSource

CollectionViewSource tracks the Current Item, so changing the value in one ComboBox will change it in all ComboBoxes

Rachel
  • 130,264
  • 66
  • 304
  • 490
  • I need to track the Current Item so I know what to populate ComboBoxes B & C with. However, I do not want it to affect all rows. – Paxenos Jan 25 '12 at 20:43
  • ComboBox B populates based off of the CurrentItem in A and C populates based off of the CurrentItem of B. – Paxenos Jan 25 '12 at 20:50
  • @Paxenos The selected item should be tracked in your data object, not in your collection. For example, bind `ComboBoxA.SelectedItem` to `SelectedItemA`, `ComboBoxB.SelectedItem` to `SelectedItemA.SelectedItemB`, and `ComboBoxC` to `SelectedItemA.SelectedItemB.SelectedItemC` – Rachel Jan 25 '12 at 20:59
  • Should the Collections to populate the ComboBoxes be kept in the data object as well? – Paxenos Jan 25 '12 at 21:04
  • @Paxenos No, those items seem static and should be stored elsewhere. Usually in this sort of case I will have a Static list of all my ComboBoxA items, and each ComboBoxA item will have its list of ComboBoxB items and so on. In the binding I will set the ItemsSource equal to the static list of items, and the `SelectedItem` equal to the item on the data object. The item on the data object is usually stored as a key, such as an integer, and a public property is exposed that returns the `StaticList.FirstOrDefault(p => p.key == DataItemKey)` – Rachel Jan 25 '12 at 21:07
  • So, if I understand this correctly, I should set ComboBoxB.ItemSource = to ((SelectedItemAType)SelectedItemA).BList? – Paxenos Jan 25 '12 at 21:13
  • Sure that would work, but you don't need the cast in your binding. Simply binding `ItemsSource="{Binding SelectedItemA.BList}"` should work fine. Also, I had my earlier comment mistaken. You should store the selected item B and C on the data object with A, not on the SelectedItemA object itself. `` – Rachel Jan 25 '12 at 21:17
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/7061/discussion-between-paxenos-and-rachel) – Paxenos Jan 26 '12 at 01:16