tags:

views:

13698

answers:

6

Update

After a bit of investigating. What seems to be the issue is that the SelectedValue/SelectedItem is occurring before the Item source is finished loading. If I sit in a break point and weight a few seconds it works as expected. Don't know how I'm going to get around this one.

End Update

I have an application using in WPF using MVVM with a ComboBox. Below is the ViewModel Example. The issue I'm having is when we leave our page and migrate back the ComboBox is not selecting the current Value that is selected.

View Model

public class MyViewModel
{
     private MyObject _selectedObject;
     private Collection<Object2> _objects;
     private IModel _model;

     public MyViewModel(IModel model)
    {
         _model = model;
         _objects = _model.GetObjects();
    }

    public Collection<MyObject> Objects
    {
         get
         {
              return _objects;
         }
         private set
         {
              _objects = value;
         }
     }

     public MyObject SelectedObject
     {
          get
          {
              return _selectedObject;
          }
          set
          {
               _selectedObject = value;
          }
      }
 }

For the sake of this example lets say MyObject has two properties (Text and Id). My XAML for the ComboBox looks like this.

XAML

<ComboBox Name="MyComboBox" Height="23"  Width="auto" 
                       SelectedItem="{Binding Path=SelectedObject,Mode=TwoWay}" 
                      ItemsSource="{Binding Objects}" DisplayMemberPath="Text" SelectedValuePath="Id">

No matter which way I configure this when I come back to the page and the object is reassembled the ComboBox will not select the value. The object is returning the correct object via the get in the property though.

I'm not sure if this is just an issue with the way the ComboBox and MVVM pattern works. The text box binding we are doing works correctly.

+5  A: 

Have you tried implementing INotifyPropertyChanged in your viewmodel, and then raise the PropertyChanged event when the SelectedItem gets set?

If this in itself doesn't fix it, then you will be able to manually raise the PropertyChanged event yourself when navigating back to the page, and that should be enough to get WPF to redraw itself and show the correct selected item.

Orion Edwards
Our actual implementation Inherits from a ViewBase class which implements INotifyPropertyChanged. I am raising the PropertyChange but the combo box remains blank.
cjibo
Even better if I put break points in and wait a bit it works. Me thinks my selecteditem is getting set before the binding of the combobox is done. Urgh.
cjibo
I forgot to raise the PorpertyChanged event on navigation back to the page.
cjibo
A: 

I have had similar issues and it was solved by making sure I was implementing IEquatable properly. When the binding occurs, it is trying to see if the objects match so make sure you are properly implementing your equality checking.

I have now tried this also. I implemented IEquatable on MyObject and match the .id fields and return true. That also is not having an effect. If I add a Textbox bound to the Property it is showing the correct information upon return to the page.
cjibo
+1  A: 

I have noticed this behavior before as well. I have noticed that the SelectedIndex property doesn't cause the same bug. If you can restructure your ViewModel to expose the index of the selected item, and bind to that, you should be good to go.

Abe Heidebrecht
A: 

It could be the way you are applying the DataContext to the Page. In WPF, everytime you navigate to a Page everything gets re-initialized, constructor gets called, loaded methods, everything. so if you are setting your DataContext inside your View you will no doubt be blowing away that SelectedItem that the user selected. In order to avoid that use the KeepAlive property of your pages.

<Page KeepAlive="True" ...>
   ...
</Page>

This will result in only the Loaded event being fired when navigating back to a page you have already visited. So you will need to ensure that you are setting the DataContext on Initialize (either externally or within the constructor) rather than Load.

However, this will only work for that instance of the Page. If you navigate to a new instance of that page it constructor will be called again.

markti
Because I am using the MVVM pattern there is no code behind for the XAML pages. There is no Load event. Everything is taking place via databinding. For that matter the template is being selected by a DataTemplateSelector based on a property in the View Model.
cjibo
A: 

Hi, I had the same problem. The thing is. The selected item doesnt know which object it should use from the collection. So you have to say to the selected item to use the item from the collection.

public MyObject SelectedObject
 {
      get
      {
          Objects.find(x => x.id == _selectedObject.id)
          return _selectedObject;
      }
      set
      {
           _selectedObject = value;
      }
 }

I hope this helps.

StefanHa
A: 

ComboBox.SelectionBoxItem.ToString()

Sean Campbell