0

I have a ShellViewModel containing three properties of type ViewModel:

  1. One public CurrentScreen property;
  2. Two private: FirstViewModel and SecondViewModel properties.

FirstViewModel has an ObservableCollection<Foo> FooCollection and a SelectedFoo property of type Foo. It's two-way bound to a DataGrid in the View, which is a DataTemplate:

<DataGrid x:Name="setupsSensoresDataGrid"           
    ItemsSource="{Binding Source={StaticResource FooCollectionViewSource}}"
    SelectedItem="{Binding SelectedFoo, Mode=TwoWay}">
    ....

The problem is, when I am at the first screen and select an item, when I go to the second screen and come back, the selection is lost.

I would like to know how to preserve selection (both visually and logically) while switching from one screen to the other.

It seems to me that the TwoWay data binding is de-selecting SelectedFoo when the View (a DataTemplate) is navigated away.

heltonbiker
  • 26,657
  • 28
  • 137
  • 252
  • Possible duplicate (but with a somewhat inelegant solution IMO): http://stackoverflow.com/questions/8808076/how-to-preserve-the-full-state-of-the-view-when-navigating-between-views-in-an-m – heltonbiker Dec 15 '15 at 20:12
  • 1
    Can you provide your view model code? Perhaps you're instantiating a new view model each time the data template is changed which therefore **resets** the `SelectedFoo` property? – Mike Eason Dec 15 '15 at 22:29

1 Answers1

1

Do you mean that your current selection (SelectedFoo) is getting lost when your CurrentScreen changes? If so, this is usually a result of a Selector's SelectedItem property getting set to null when its ItemsSource property is changed.

The way I usually work around this is to make the backing field used to hold the selection (ie. the backing field for SelectedFoo in your case) a static field: this should then retain the selection (as long as you are not recreating your view models each time).

For example:

public Foo SelectedFoo
{
    get
    {
        return _selectedFoo;
    }
    set
    {
        if (_selectedFoo != value)
        {
            _selectedFoo = value;
            // INotifyPropertyChanged event dispatch...
        }
    }
}
static Foo _selectedFoo;

Note that only the backing field is static, the property need not be, although it wouldn't make any difference.

Obviously this will only work if you are using a single instance of the view model (that contains the property) at any given time. If there are a bunch of them in a list, for example, then this technique would not work as all of them would be sharing the same backing field.

Occasionally, you may also need to explicitly check for null in the property setter. In other words, change the line:

if (_selectedFoo != value)

to:

if (value != null && _selectedFoo != value)

I've used both variants of this technique in the past.

Steven Rands
  • 5,160
  • 3
  • 27
  • 56