¿Cómo actualizar automáticamente el filtro y / o el orden de clasificación en CollectionViewSource, cuando cambia la propiedad de un elemento individual?

Ok, entonces esta pregunta está relacionada con Windows Phone 7 / Silverlight (herramientas WP7 actualizadas, septiembre de 2010), específicamente filtrando un subyacenteObservableCollection<T>.

Al jugar con la aplicación de control de Pivot de plantilla WP7, me he encontrado con un problema por el cual cambiar un elemento subyacente en unObservableCollection<T>, no da como resultado que se actualice ListBox en pantalla. Básicamente, la aplicación de muestra tiene dos pivotes, el primero directamente vinculado al subyacenteObservableCollection<T>, y el segundo vinculado a unCollectionViewSource&nbsp;(es decir, que representa una vista filtrada en el subyacenteObservableCollection<T>)

Los elementos subyacentes que se agregan alObservableCollection<T>&nbsp;implementarINotifyPropertyChanged, al igual que:

public class ItemViewModel : INotifyPropertyChanged
{       
    public string LineOne
    {
        get { return _lineOne; }
        set
        {
            if (value != _lineOne)
            {
                _lineOne = value;
                NotifyPropertyChanged("LineOne");
            }
        }
    } private string _lineOne;

    public string LineTwo
    {
        get { return _lineTwo; }
        set
        {
            if (value != _lineTwo)
            {
                _lineTwo = value;
                NotifyPropertyChanged("LineTwo");
            }
        }
    } private string _lineTwo;

    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            if (value != _isSelected)
            {
                _isSelected = value;
                NotifyPropertyChanged("IsSelected");
            }
        }
    } private bool _isSelected = false;

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Luego, en la clase principal, se confecciona una recopilación de datos (la lista se reduce por brevedad, también tenga en cuenta que, a diferencia de otros elementos, tres de las entradas LoadData () tienen IsSelected == true):

 public class MainViewModel : INotifyPropertyChanged
 {
  public MainViewModel()
  {
   this.Items = new ObservableCollection<ItemViewModel>();
  }

  public ObservableCollection<ItemViewModel> Items { get; private set; }

  public bool IsDataLoaded
  {
   get;
   private set;
  }

   public void LoadData()
  {
   this.Items.Add(new ItemViewModel() { LineOne = "runtime one", IsSelected = true, LineTwo = "Maecenas praesent accumsan bibendum" });
   this.Items.Add(new ItemViewModel() { LineOne = "runtime two", LineTwo = "Dictumst eleifend facilisi faucibus" });
   this.Items.Add(new ItemViewModel() { LineOne = "runtime three", IsSelected = true, LineTwo = "Habitant inceptos interdum lobortis" });
   this.Items.Add(new ItemViewModel() { LineOne = "runtime four", LineTwo = "Nascetur pharetra placerat pulvinar" });
   this.Items.Add(new ItemViewModel() { LineOne = "runtime five", IsSelected = true, LineTwo = "Maecenas praesent accumsan bibendum" });
   this.Items.Add(new ItemViewModel() { LineOne = "runtime six", LineTwo = "Dictumst eleifend facilisi faucibus" });
   this.IsDataLoaded = true;
  }

  public event PropertyChangedEventHandler PropertyChanged;
  public void NotifyPropertyChanged(String propertyName)
  {
   if (null != PropertyChanged)
   {
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
   }
  }
 }

En el archivo MainPage.xaml, el primer Pivot tiene suItemSource&nbsp;basado directamente en elObservableCollection<T>&nbsp;lista. Dentro del segundo Pivot, el ListBox en pantalla tiene suItemSource&nbsp;Propiedad establecida en unCollectionViewSource, cuya fuente subyacente se basa en elObservableCollection<T>&nbsp;poblado enLoadData()&nbsp;encima.

<phone:PhoneApplicationPage.Resources>
    <CollectionViewSource x:Key="IsSelectedCollectionView" Filter="CollectionViewSource_SelectedListFilter">
    </CollectionViewSource>
</phone:PhoneApplicationPage.Resources>

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
    <!--Pivot Control-->
    <controls:Pivot Title="MY APPLICATION">
        <!--Pivot item one-->
        <controls:PivotItem Header="first">
            <!--Double line list with text wrapping-->
            <ListBox x:Name="FirstListBox" Margin="0,0,-12,0" ItemsSource="{Binding Items}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                      <StackPanel Margin="0,0,0,17" Width="432">
                          <TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                          <TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                      </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </controls:PivotItem>

        <!--Pivot item two-->
        <controls:PivotItem Header="second"> 
            <!--Triple line list no text wrapping-->
            <ListBox x:Name="SecondListBox" Margin="0,0,-12,0" ItemsSource="{Binding  Source={StaticResource IsSelectedCollectionView}}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Margin="0,0,0,17">
                                <TextBlock Text="{Binding LineOne}" TextWrapping="NoWrap" Margin="12,0,0,0" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                                <TextBlock Text="{Binding LineThree}" TextWrapping="NoWrap" Margin="12,-6,0,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
        </controls:PivotItem>
    </controls:Pivot>
</Grid>

<!--Sample code showing usage of ApplicationBar-->
<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1" Click="ApplicationBarIconButton_Click"/>
        <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>
        <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem Text="MenuItem 1"/>
            <shell:ApplicationBarMenuItem Text="MenuItem 2"/>
        </shell:ApplicationBar.MenuItems>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

Tenga en cuenta que en MainPage.xaml.cs, elFilter&nbsp;atributo en elCollectionViewSource&nbsp;en elResources&nbsp;la sección anterior tiene asignado un controlador de filtro, que examina los elementos que tienenIsSelected&nbsp;establecido en verdadero:

public partial class MainPage : PhoneApplicationPage
{
    public MainPage()
    {
        InitializeComponent();
        DataContext = App.ViewModel;
        this.Loaded += new RoutedEventHandler(MainPage_Loaded);
    }

    private void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        if (!App.ViewModel.IsDataLoaded)
        {
            App.ViewModel.LoadData();
            CollectionViewSource isSelectedListView = this.Resources["IsSelectedCollectionView"] as CollectionViewSource;
            if (isSelectedListView != null)
            {
                isSelectedListView .Source = App.ViewModel.Items;
            }
        }
    }

    private void CollectionViewSource_SelectedListFilter(object sender, System.Windows.Data.FilterEventArgs e)
    {
        e.Accepted = ((ItemViewModel)e.Item).IsSelected;
    }

    private void ApplicationBarIconButton_Click(object sender, EventArgs e)
    {
        ItemViewModel item = App.ViewModel.Items[App.ViewModel.Items.Count - 1];
        item.IsSelected = !item.IsSelected;
    }
}

También tenga en cuenta que inmediatamente después de cargar los datos, obtengo elCollectionViewSource&nbsp;y establece su fuente de datos comoObservableCollection<T>&nbsp;lista, para que haya datos base sobre los que pueda tener lugar el filtrado.

Cuando se carga la aplicación, los datos se muestran como se esperaba, con esos elementos en elObservableCollection<T>&nbsp;cual tieneIsSelected&nbsp;cierto, se muestra en el segundo Pivot:

Notarás que he descomentado los iconos de la barra de aplicaciones, el primero de los cuales alterna elIsSelected&nbsp;propiedad del último elemento en elObservableCollection<T>&nbsp;cuando se hace clic (ver la última función en MainPage.xaml.cs).

Aquí está el quid de mi pregunta&nbsp;- Cuando hago clic en el icono de la barra correspondiente, puedo ver cuándo el último elemento de la lista tiene suIsSelected&nbsp;propiedad establecida en true, sin embargo, el segundo Pivot no muestra este elemento modificado. Puedo ver que elNotifyPropertyChanged()&nbsp;se está disparando el controlador sobre el elemento, sin embargo, la colección no está detectando este hecho, y por lo tanto, el cuadro de lista en Pivot 2 no cambia para reflejar el hecho de que debería haber un nuevo elemento agregado a la colección.

Estoy bastante seguro de que me estoy perdiendo algo bastante fundamental / básico aquí, pero si eso falla, ¿alguien sabe la mejor manera de obtener la colección y sus elementos subyacentes para jugar felices juntos?

Supongo que este problema también se aplica a la clasificación y al filtrado ((en el sentido de que si unCollectionViewSource&nbsp;se basa en la clasificación, luego, cuando cambia una propiedad de un elemento que se usa en la clasificación, el orden de clasificación de la colección también debería reflejar esto))