2

I have a ListView in UWP Application which binds 100 items on 1st load, then after loading is completed it binds another 100 i.e. it is incrementally loaded.

Here is a code :

<ListView x:Name="lstWords" ItemsSource="{Binding Items}" DataFetchSize="1" IncrementalLoadingTrigger="Edge" IncrementalLoadingThreshold="5" SelectionChanged="lstItems_SelectionChanged">
   <ListView.ItemTemplate>
     <DataTemplate>
       <StackPanel>
         <TextBlock Text="{Binding Name}"></TextBlock>
         <TextBlock Text="{Binding ID}" Visibility="Collapsed"></TextBlock>
       </StackPanel>
     </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

And the code which binds This ListView with incremental loading (Lazy loading) is as follows :

public class IncrementalLoadingCollection : ObservableCollection<Words>, ISupportIncrementalLoading
{
    uint x = 1;
    public bool HasMoreItems { get { return x < 10000; } }
    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        var page = new Index();
        string Id = localSettings.Values["Id"].ToString();
        return AsyncInfo.Run(async cancelToken =>
        {
            var apiData = await page.GetData(Id, x.ToString()); 
            foreach (var i in apiData)
            { 
                Add(new Words()
                {
                    Name = i.Name, ID=i.ID
                });
            }
            x += (uint)apiData.Count(); 
            return new LoadMoreItemsResult { Count = (uint)apiData.Count() };
        });
    }
}

public class ViewModelWords
{
    public ViewModelWords()
    {
        Items = new IncrementalLoadingCollection();
    } 
    public IncrementalLoadingCollection Items { get; set; }
}

The code for GetData() method mentioned here is in another class Index & is as follows :

public sealed partial class Index : Page
{
  List<Words> loadedList = new List<Words>();
  public class Words
  {
     public string ID { get; set; }
     public string Name { get; set; }
     public override string ToString() { return this.Name; }
  }


  public async Task<IEnumerable<Words>> GetData(string Id, string limit)
  {
     string mainUrlForWords = ApiUrl

      using (var httpClient = new HttpClient())
      {
         var dataUri = await httpClient.GetStringAsync(mainUrlForWords);
         JsonObject jsonObject = JsonObject.Parse(dataUri.ToString());
         JsonArray jsonArray = jsonObject["payload"].GetArray();
         foreach (JsonValue groupValue in jsonArray)
         {
            JsonObject groupObject = groupValue.GetObject();
            loadedList.Add(new Words { Name = groupObject.GetNamedString("name"), ID = groupObject.GetNamedString("id") });
         }
         return loadedList;
       }
   }
}

As mentioned in the question i want to implement searchBox functionality for above ListView i.e. the List is already loaded with items say 100 items, now in searchBox i will enter any word/text for the matches in items in the ListView, it should return only matched items based on word/text entered.

e.g. suppose listview items are as follows :

Abbasds, Abbsdf, ABCdef, Adehf

If i type 'ab' it must return following items : Abbasds, Abbsdf, ABCdef

If i type 'Abb' is must return : Abbasds, Abbsdf

I have tried implementing the said functionality using following code :

 <SearchBox x:Name="searchWords" QueryChanged="search_Words" PlaceholderText="Filter by..."></SearchBox>


private void search_Words(SearchBox sender, SearchBoxQueryChangedEventArgs e)
    {
        if (loadedList.Count>0)
        {
            lstWords.ItemsSource = loadedList.Where(a => a.ToString().ToUpper().Contains(searchWords.QueryText.ToUpper()));
        }
    }

But it fails to achieve the said functionality. When i debugged the code loadedList.count showed 0. while on App View ListView is loaded with items & can be seen on UI page.

Can anyone figure this out or provide some appropriate solution for the SearchBox functionality??

ace
  • 225
  • 4
  • 18

1 Answers1

1

Your IncrementalLoadingCollection creates a new instance of an Index page which makes no sense at all.

I guess you simply want to get the items from the ListBox:

private void search_Words(SearchBox sender, SearchBoxQueryChangedEventArgs e)
{
    lstWords.ItemsSource = listBox.Items.OfType<Words>().Where(a => a.ToString().ToUpper().Contains(searchWords.QueryText.ToUpper())).ToArray();
}
mm8
  • 163,881
  • 10
  • 57
  • 88
  • Your solution looks quite good, but here are few complications : what is `listBox` in this case? also suppose if there are 100 items which are binded to the ListView & if i type 'ab' in searchBox it will return items starting with `ab` & that's fine, but if i removed 'b' from 'ab' by using backspace, then in that case your condition will fail. As in suppose from 100 items there are 30 items which matches querystring 'ab'.. next time if i remove 'b' from 'ab' then it will return items starting with 'a' from those 30 items only, not from the 100 items. – ace Aug 24 '18 at 05:49
  • listBox is the ListBox in the view. I assume that the SearchBox and the ListBox belong to the same view. – mm8 Aug 24 '18 at 09:38
  • then it will be like `lstWords.ItemsSource = lstWords.Items.OfType().......` And in this case if i backspace any character from search query then the condition will fail. i.e. if searchQuery : `ab` returns 10 records, then after backspacing `b` from `ab` it will search string within those 10 items only & not in all items, i.e. 100 in this case!!!! – ace Aug 24 '18 at 10:07
  • @ace So in this case, you should create query from those 10 items and select the compatible items as the `ItemsSource` to make them display in the result. – Breeze Liu - MSFT Aug 28 '18 at 06:53
  • @BreezeLiu-MSFT yeah that thing is working, what i want is to search items in all 100 available items & not in 10 items – ace Aug 28 '18 at 10:16
  • That should be similar to query the 10 items, you should query the corresponding items from all your resource but not the diplayed items resource from search `ab`. May be the data source has changed, you should make sure the resource is correct. – Breeze Liu - MSFT Aug 29 '18 at 02:45