I’m creating an application with a weather map that shows the heat as a Pushpin at different places. To do this, supplied by own PushpinModel that supports the INotifyPropertyChanged interface:
public class PushpinModel: INotifyPropertyChanged
{
#region // events
public event PropertyChangedEventHandler PropertyChanged;
#endregion events
#region // fields
Heat heat = Heat.normal;
#endregion fields
#region // properties
public string Placename { get; set; }
public GeoCoordinate Location { get; set; }
public Heat Heat
{
get { return heat; }
set
{
if (heat != value)
{
heat = value;
OnPropertyChanged("Heat");
}
}
}
public string IDno { get; set; }
#endregion properties
#region // handlers
protected virtual void OnPropertyChanged(string propChanged)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propChanged));
}
#endregion handlers
}
The PushpinModel objects are contained in an ObservableCollection called Pushpins which are periodically updated to ShowWeather:
public class Pushpins: ObservableCollection<PushpinModel>
{
#region // METHODS
public void ShowWeather( WeatherReport fromWeatherReport)
{
foreach (WeatherRecord w in fromWeatherReport.WeatherRecords)
{
this.First<PushpinModel>(p => p.IDno == w.PlaceID).Heat = w.Heat;
}
}
#endregion methods
}
I display the Pushpins on a Bing Map, but also as items in an ItemsControl:
<ItemsControl x:Name="ItemList" ItemsSource="{Binding Source={StaticResource placesSortedAndFiltered}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border>
<TextBlock Text="{Binding Placename}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The ItemsSource is defined as a CollectionViewSource:
<CollectionViewSource x:Key="placesSortedAndFiltered" Source="{Binding ElementName=MyMainPage, Path=Pushpins}" Filter="PlaceHeat_Filter">
<CollectionViewSource.SortDescriptions>
<componentmodel:SortDescription PropertyName="Placename" Direction="Ascending" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
with a Filter in the codebehind defined as:
private void PlaceHeat_Filter(object sender, FilterEventArgs e)
{
e.Accepted = (((PushpinModel)e.Item).Heat != Heat.na);
}
where a public enum Heat {na,cool,normal,warm,hot}
The problem is that ItemsControl list display appropriately sorted and filtered on page load, but does NOT update when the PushpinModel objects properties are changed. Please note that when the Pushpins object is bound to a Bing Map Control, the PushpinModel objects do update as expected. So somehow, my ItemsControl list isn’t updating even though it is bound via a CollectionView to an ObservableCollection
I believe that the
CollectionViewSourceimplementation only supports automatic filtering when the underlying collection is changed (or reset). The filter does not get invoked if a property of an underlying data item changes.You could either call
Refresh()on theCollectionViewSourcewhen a property for an item in the collection changes, or you could implement your ownCollectionViewSourcewhich listens to property changed events on underlying data objects, or you could bind directly to a filtered (and sorted) collection rather than using theCollectionViewSource.