Fafnr
Fafnr

Reputation: 257

Databinding both ComboBox.ItemsSource and SelectedItem results in SelectedItem being set too early

I have a strange WPF problem I first noticed in a Developer Express component (issue at http://www.devexpress.com/Support/Center/p/Q352950.aspx).

Comboboxes seem to databind SelectedItem way too early, and I can't seem to figure out what to do about it.

Copying from the developer express issue (with some changes for clarity):

I have the following comboboxedit in my XAML:

<dxe:ComboBoxEdit Name="CharacteristicDropdown" ItemsSource="{Binding Path=Characteristics}" SelectedItem="{Binding Path=StratifyCharacteristic}" ValueMember="CharacteristicName" DisplayMember="CharacteristicName" />

(Note - the same problem apparently exists due to the normal ComboBox, so I've just kept the code here)

My problem is that SelectedItem is set much sooner than I expect. When ItemsSource changes, the first item in it becomes the SelectedItem. This is extremely illogical - it is NOT selected, just because it is now in the list. Furthermore, it is not actually visually selected in the combobox. I want SelectedItem to be set when I actually select an item, via code or UI interaction, not just when I change the ItemsSource.

Just to be completely clear, this is the chain of events:

1) I have a Grid databound to a BindingList of items

2) I have a ComboBox databount to the same BindingList as the grid

3) I use the Grid to add something to this list. (This is fired even before the item is completely filled out in the grid, however this doesn't matter.)

4) Combobox's SelectedItem is set automatically! This happens simply because the backing list for the combobox now has an item.

Note, that I have not actually selected anything. I've simply added to the backing list. However, having simply added to the backing list, I now have a SelectedItem, even though visually the item is not selected. Furthermore, if I NOW try to to select the item from the dropdown, the SelectedItem is NOT set again!

This is driving me crazy - does anyone have a solution?

Upvotes: 0

Views: 5957

Answers (2)

Steve Greatrex
Steve Greatrex

Reputation: 15999

I would suggest that you switch to using an ICollectionView:

Replace your public property with a new one:

public ViewModel()
{
    this.CharacteristicsView = CollectionViewSource.GetDefaultView(this.Characteristics);
}

public ICollectionView CharacteristicsView { get; private set; }

Change your binding to point to the new property and set IsSynchronizedWithCurrentItem to true:

<ComboBox ItemsSource="{Binding Path=CharacteristicsView}" 
        IsSynchronizedWithCurrentItem="True" ValueMember="CharacteristicName"
        DisplayMember="CharacteristicName" />

Wherever you need to access the current item, use the CurrentItem property of the view:

var currentItem = this.CharacteristicsView.CurrentItem;

Upvotes: 0

Emy
Emy

Reputation: 91

From the sound of things when you add an item to your grid it is updating the property that your combobox's itemsource is bound to, and then the combobox see's that the source has been changed and then selects the first item in the collection. It would be helpful to see the datagrid's xaml code as well to see its binding.

A couple of suggestions:

1)instead of a binding list try using an IEnumerable collection like so:

private ObservableCollection<Drink> drinks = new ObservableCollection<Drink>();

public IEnumerable<Drink> DrinkCollection
     {
         get { return this.drinks; }
     }

and bind the combo to the property.

2) Have a play around with the UpdateSourceTrigger and SynchronizeWithCurrentItem properties in your xaml.

3) create a separate property for your combo.

Upvotes: 3

Related Questions