【问题标题】:How to implement SearchBox functionality in incrementally(Lazy) loaded ListView of UWP如何在 UWP 的增量(惰性)加载 ListView 中实现 SearchBox 功能
【发布时间】:2025-12-08 12:20:02
【问题描述】:

我在 UWP 应用程序中有一个 ListView,它在第一次加载时绑定 100 个项目,然后在加载完成后绑定另外 100 个,即增量加载。

这是一个代码:

<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>

将这个ListView与增量加载(延迟加载)绑定的代码如下:

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; }
}

这里提到的GetData()方法的代码在另一个类Index &中,如下:

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;
       }
   }
}

正如问题中提到的,我想为上面的 ListView 实现 searchBox 功能,即 List 已经加载了 100 个项目,现在在 searchBox 我将为 ListView 中项目的匹配项输入任何单词/文本,它应该根据输入的单词/文本仅返回匹配的项目。

例如假设列表视图项如下:

Abbasds, Abbsdf, ABCdef, Adhef

如果我输入'ab',它必须返回以下项目:Abbasds、Abbsdf、ABCdef

如果我输入“Abb”,则必须返回:Abbasds, Abbsdf

我已尝试使用以下代码实现上述功能:

 <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()));
        }
    }

但它无法实现上述功能。 当我调试代码时,loadedList.count 显示为 0。而在 App View ListView 中加载了项目并且可以在 UI 页面上看到。

任何人都可以解决这个问题或为 SearchBox 功能提供一些适当的解决方案吗?

【问题讨论】:

  • 什么是loadedList,你在视图中的哪里初始化这个字段?
  • 为什么不使用CollectionView
  • @TomerAgmon1 您能否通过编码示例提供更多关于CollectionView 的指导?
  • @mm8 loadedList&lt;Words&gt; 类型的列表,请参阅更新后的问题和代码
  • 这里是link 关于CollectionView 的代码示例。

标签: xaml listview uwp search-box


【解决方案1】:

您的 IncrementalLoadingCollection 创建了一个 Index 页面的新实例,这完全没有意义。

我猜你只是想从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();
}

【讨论】:

  • 您的解决方案看起来相当不错,但这里有一些复杂之处:在这种情况下,listBox 是什么?还假设如果有 100 个项目绑定到 ListView 并且如果我在 searchBox 中键入“ab”,它将返回以 ab 开头的项目,这很好,但是如果我使用退格从“ab”中删除了“b”,那么在这种情况下,您的条件将失败。假设从 100 个项目中有 30 个项目与查询字符串“ab”匹配。下次如果我从“ab”中删除“b”,那么它将仅从这 30 个项目中返回以“a”开头的项目,而不是从 100 个项目中返回项目。
  • listBox 是视图中的 ListBox。我假设 SearchBox 和 ListBox 属于同一个视图。
  • 那么它将像lstWords.ItemsSource = lstWords.Items.OfType&lt;Words&gt;()....... 在这种情况下,如果我退格搜索查询中的任何字符,则条件将失败。即如果 searchQuery : ab 返回 10 条记录,则在从 ab 退格 b 之后,它将仅在这 10 个项目中搜索字符串,而不是在所有项目中搜索字符串,即在这种情况下为 100!!!!
  • @ace 所以在这种情况下,您应该从这 10 个项目中创建查询,并选择兼容的项目作为 ItemsSource 以使其显示在结果中。
  • @BreezeLiu-MSFT 是的,那东西正在工作,我想要的是在所有 100 个可用项目中搜索项目,而不是在 10 个项目中搜索
最近更新 更多