I am trying to develop a page in a WP8 app which has a search box at the top and a list of items that match the search below, updating as the search box updates. Pretty straightforward, right? Except I can't get it to work.
After perusing StackOverflow and the interwebz, the recommended solution seems to be to use CollectionViewSource
. Well, I'm trying to use it and no items show up. As soon as I switch to the ObservableCollection
containing my items in XAML, everything shows up fine.
My data is loaded asynchronously from a DB.
XAML
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<toolkit:PhoneTextBox Grid.Row="0" Hint="search query" ActionIcon="/Assets/Search.png" Text="{Binding SearchQuery, Mode=TwoWay}">
<i:Interaction.Behaviors>
<themes:TextBoxUpdateOnTextChangedBehavior />
</i:Interaction.Behaviors>
</toolkit:PhoneTextBox>
<phone:LongListSelector Grid.Row="1" ItemsSource="{Binding SearchResults}" />
<!-- I have also tried binding to SearchResults.View with no success -->
</Grid>
View Model
public class MyViewModel
{
private ObservableCollection<MyItemViewModel> _allItems = new ObservableCollection<MyItemViewModel>();
public CollectionViewSource SearchResults { get; private set; }
public MyViewModel()
{
SearchResults = new CollectionViewSource { Source = _allItems };
_allItems.CollectionChanged += (_, __) => SearchResults.View.Refresh();
LoadAllItemsAsync();
}
private async void LoadAllItemsAsync()
{
IList<MyItemModel> models = await LoadMyModels();
_allItems.AddRange(models.Select(model => new MyItemViewModel(model)));
}
}
As you can see, I haven't even attempted to write filtering code yet. Shouldn't the code above basically show a LongListSelector with all the items I have loaded? If I change the SearchResults
type to ObservableCollection<MyItemViewModel>
and have the getter return _allItems
, my page shows the expected items. What am I doing wrong here?
The problem is that the LongListSelector
control requires that its ItemsSource
implements IList
, which CollectionViewSource doesn't do. This means you can't bind a CollectionViewSource
to a LongListSelector
out of the box. You can see this by trying to set it in the code-behind file like this:
myLongListSelector.ItemsSource = myCollectionViewSource.View;
Which gives an error saying it can't convert the view to an IList
.
I know atleast two solutions to this, one is to write a wrapper class around CollectionViewSource which does implement IList and then bind to that. Another question gives an example of this (I haven't tried it thought): LongListSelector grouping using CollectionView in Windows Phone 7 or Windows Phone 8
Another method is to not use CollectionViewSource
and instead using System.Linq
for sorting like suggested in this question: How to Sort a LongListSelector in Windows Phone
来源:https://stackoverflow.com/questions/22111601/windows-phone-collectionviewsort-not-showing-anything