Strange issue binding to ComboBox where the display value sometimes shows up blank

I'm seeing a strange issue when binding to ComboBox where the display value sometimes shows up blank. The case is repeatable however and happens the second time a dialog opened from another parent form. If the parent form is closed and reopened then the first time it's child dialog is opened the contained WPF ComboBox shows the display property correctly. If I then close the dialog and relaunch it again from the same parent form the ComboBox shows no display value even though I can verify the same bound properties are being hit in my ViewModel.

<ComboBox ItemsSource="{Binding AvailableVehicles}"
          SelectedValuePath="Value"
          SelectedValue="{Binding SelectedVehicle, Mode=TwoWay}"
          DisplayValuePath="Value.Model" />

To explain the data structure for my ViewModel it's basically just a class that exposes an AvailableVehicles collection which houses a objects which are similar to the Nullable<> type in that it wraps a Vehicle object and exposes it through a Value property. Each Vehicle then has a Model and Cost property.

I've been troubleshooting this now for longer than a day and I've pretty much ruled out everything but this being a bug in the ComboBox itself. So at this point I'm hoping for a reasonable workaround but if somebody can actually help point out a flaw in my code that would be great too.

Notes:

  • I haven't been able to get this problem to reproduce in a more simple single Window WPF example.
  • The WinForms interop scenario where I have an MDI parent Form and child forms that house WPF UserControls in case that may be relevant.
  • If I set IsAsync to True on either the ItemsSource or the SelectedValue bindings the problem no longer occurs.
  • If I make DisplayValuePath instead into a ItemsTemplate and in the binding within the defined DataTemplate I place a converter, I've noticed that the value passed in is null instead of the expected value.

Answers


I had the same problem and only solution what I've found was create two properties in my ViewModel. One as the selected value (Value) but it is not bound to ComboBox and one for binding (SelectedItem) which is bound to SelectedItem. In SelectedItem getter i return Values.FirstOrDefault(x => x.Value == Value) and in setter i set the Value by value.Value. And at last when Value has been changed in OnValueChanged property i notify View about change of SelectedItem ( NotifyPropertyChanged("SelectedItem"))...


I believe the problem had to do with the object bound to SelectedValue and the objects that were bound to the ItemsSource were essentially different instances of the same data and happened to be be instances of classes that didn't override Equals or the == operator and the like. From what I've experienced a few times now is that since the SelectedValue or in some cases the SelectedItem does not technically equal any objects in the bound ItemsSource then it is ignored and you will get a blank value shown in the UI.

The problem in this particular situation was likely I was reusing the selected value when the form was closed but the lockup list was probably being regenerated every time the dialog was opened.

So when I see this symptom in any code that I come across now my first thing to check is the item types being bound and ensure that the SelectedValue or SelectedItem is truly either ReferenceEquals or Equals with one of the items in the ItemsSource. For now I'll just chalk this one up again to the poor support for reasonable binding error feedback in WPF.


I struggled with this problem for about one week and still don't know what caused such a strange behavior of combobox.

After raising OnPropertyChanged against combobox's ItemsSource (@Jeronimo the Black case), classical combobox control cannot recognize that SelectedItem is still in underlying collection. Then control internals set SelectedItem=NULL and UI shows blank. Buggy thing is that such behavior 50% reproducible, after switching to another object or model, interconnection between ItemsSource and SelectedItem can self-restore.

In my case even ItemsSource filtering caused these bugs. Pay attention that ParentRegionId property has Nullable type.

eg.1 no blanks

    public IEnumerable CityDisplayList
    {
        get
        {
            if (_selectedCity != null && _selectedCity.ParentRegionId != null)
            {
                return ItemsSource.Where(x => x.ParentRegionId != null);
            }

            return Enumerable.Empty<TRegion>();
        }
    }

eg.2 50% blanks (additional filtering)

    public IEnumerable CityDisplayList
    {
        get
        {
            if (_selectedCity != null && _selectedCity.ParentRegionId != null)
            {
                return ItemsSource.Where(x => x.ParentRegionId != null && x.ParentRegionId == _selectedCity.ParentRegionId);
            }

            return Enumerable.Empty<TRegion>();
        }
    }

eg.3 50% blanks (IsAsync = True in binding statement)

ItemsSource="{Binding CityDisplayList, Mode=OneWay, IsAsync=True}"

I support the idea of @jpierson that its better not to use SelectedItem at all if your underlying collection and SelectedItem were created in different class instances or when they have different datacontext source. For example i used dependency property to pass SelectedItem into UserControl. However, ItemsSource was a part of other UC context.

The easiest way to solve this is just to forget about SelectedItem property:

<ComboBox x:Name="cbxCity" ItemsSource="{Binding CityDisplayList}" DisplayMemberPath="RegionName"
              SelectedItem="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:ControlRegionCombobox}}, Path=SelectedCity}" />

and to use "SelectedValue" + "SelectedValuePath" instead:

<ComboBox x:Name="cbxCity" ItemsSource="{Binding CityDisplayList}" DisplayMemberPath="RegionName"
              SelectedValue="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:ControlRegionCombobox}}, Path=SelectedCity.Id}"
              SelectedValuePath="Id" />

Need Your Help

How do I store objects created into an ArrayList and return it?

java object arraylist abstract-class extends

I'm asked to create a method called listOfWorkers in which i will create objects of each type of the 3 workers I have by reading the data from the file "workers.txt" and then store the objects into...

Subscribing to external ical programmatically

google-api google-calendar-api google-apps icalendar

Through the Google Calendar UI a user can add an external iCAL calendar to their CalendarList.