实现isupportincrementloading接口- UWP - c#

本文关键字:UWP 接口 isupportincrementloading 实现 | 更新日期: 2023-09-27 18:17:15

我正在学习c#,目前正在UWP应用程序中研究ISupportIncrementalLoading,但似乎无法掌握它。它甚至在编译之前就给了我错误。我从这里得到了灵感。但是我无法理解如何在我的应用程序中实现它。

我有一个IIncrementalLoading接口和一个单独的类,它动态地向ObservableCollection<T>添加内容。如果我不实现Incremental Loading我的ObservableCollection动态地提供内容给我的SearchPage.xamlGridView,但如果我加载更多的项目,他们取代以前生成的项目,只有新的项目显示代替。

SearchPage.xaml中的代码:

<Page
x:Class="WatchfreeWebsite.SearchPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WatchfreeWebsite"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:data="using:WatchfreeWebsite"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <StackPanel>
        <TextBlock Text="Search Results"
                   FontSize="20"
                   TextAlignment="Center"/>
        <TextBlock Text="Search for Movies and TV Shows"
                   TextAlignment="Center"
                   TextWrapping="Wrap"/>
        <HyperlinkButton x:Name="IndexPageLink"
                         Content="Go to Index"
                         HorizontalAlignment="Center"
                         Click="IndexPageLink_Click"/>
    </StackPanel>
    <StackPanel Grid.Row="1">
        <TextBox x:Name="SearchInputBox" 
                 TextAlignment="Left"
                 Width="280"
                 PlaceholderText="search"
                 TextChanged="SearchInputBox_TextChanged"></TextBox>
        <TextBlock x:Name="ErrorTextBox"
                   TextWrapping="Wrap"
                   TextAlignment="Center"/>
    </StackPanel>
    <GridView Grid.Row="2"
              x:Name="SearchGrid"
              HorizontalAlignment="Center"
              ItemsSource="{x:Bind SearchList, Mode=OneWay}"
              IsItemClickEnabled="True"
              ItemClick="SearchGrid_ItemClick">
        <GridView.Header>
            <StackPanel BorderBrush="Red"
                        BorderThickness="0,0,0,1"
                        Margin="5"
                        HorizontalAlignment="Center">
                <TextBlock Text=""
                           x:Name="SearchGridHeader"
                           TextAlignment="Center"
                           Margin="0"/>
            </StackPanel>
        </GridView.Header>
        <GridView.ItemTemplate>
            <DataTemplate x:DataType="data:SearchItems">
                <StackPanel BorderThickness="0,1,0,0"
                            BorderBrush="Red"
                            Margin="5">
                    <TextBlock Text="{x:Bind SearchTitle, Mode=OneWay}"
                               TextAlignment="Center"
                               TextWrapping="Wrap"
                               Width="140"
                               Height="40"/>
                    <StackPanel BorderBrush="Red" BorderThickness="0,0,0,1"
                                Margin="0">
                        <Image x:Name="CoverImage"
                               Source="{x:Bind SearchImageLink, Mode=OneWay}"
                               Width="130"
                               Height="200"
                               Margin="0"/>
                    </StackPanel>
                </StackPanel>
            </DataTemplate>
        </GridView.ItemTemplate>
        <GridView.Footer>
            <HyperlinkButton x:Name="MoreItemsLink"
                             Content="Load more items"
                             Click="MoreItemsLink_Click"
                             Visibility="Collapsed"/>
        </GridView.Footer>
    </GridView>
</Grid>

SearchPage.xaml.cs中的代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using HtmlAgilityPack;
using static WatchfreeWebsite.HtmlDocs;

namespace WatchfreeWebsite
{
public sealed partial class SearchPage : Page
{
    HtmlDocument SearchDoc;
    public static string[] SearchLinks = new string[500];
    public static string[] SearchTitles = new string[500];
    public static string[] SearchImageLinks = new string[500];
    public static string[] SearchNextPagesLinks = new string[50];
    public static int numberOfLinks = 0;
    int numberOfTitles = 0;
    int numberOfImages = 0;
    int nextPage = 2;
    int numberOfPages = 0;
    public static int lastListItems = 0;

    //IIncrementalSource<SearchItems> SearchList = new IncrementalLoadingCollection<GetTVShows(),SearchItems>();
    int listItems = 0;
    DispatcherTimer sTimer = new DispatcherTimer();
    public SearchPage()
    {
        this.InitializeComponent();
        NavigationCacheMode = NavigationCacheMode.Enabled;
    }
    private void DeleteList(int count)
    {
        for (int x = 0; x < count; x++)
        {
            SearchList.RemoveAt(0);
        }
    }
    private async void LoadHtmlDocument(string url)
    {
        try
        {
            if (NetworkInformatiom())
            {
                SearchDoc = await new HtmlWeb().LoadFromWebAsync(url);
            }
            else
            {
                SearchDoc = null;
            }
            if (SearchDoc != null)
            {
                Links(SearchDoc);
            }
        }
        catch (Exception ex)
        {
            ErrorDialog("SearchDoc_Download_Failed'n" + ex.Message);
        }
    }
    private void Links(HtmlDocument doc)
    {
        listItems = 0;
        try
        {
            foreach (var link in doc.DocumentNode.Descendants("a").Where(pl => pl.Attributes.Contains("href")))
            {
                string dataValue = link.GetAttributeValue("href", "");
                //dataValue = ReplaceLinkStrings(dataValue);
                if (dataValue.StartsWith("/watch") && dataValue.EndsWith(".html"))
                {
                    SearchLinks[numberOfLinks] = MoviesPage.MoviesBaseLink + dataValue.Trim();
                    listItems++;
                    numberOfLinks++;
                }
            }
            ImageLinks(doc);
        }
        catch (Exception ex)
        {
            ErrorDialog("There was a problem while acquiring search links.'n" + ex.Message);
        }
    }
    private void ImageLinks(HtmlDocument doc)
    {
        try
        {
            //int LinkID = 0;
            foreach (var link in doc.DocumentNode.Descendants("img").Where(d => d.Attributes.Contains("src")))
            {
                if (link != null)
                {
                    if (link.Attributes["src"].Value == "/images/noposter.jpg")
                    {
                        SearchImageLinks[numberOfImages] = @"ms-appx:///Assets/noposter.jpg";
                    }
                    else
                    {
                        SearchImageLinks[numberOfImages] = string.Format("http:{0}", link.Attributes["src"].Value);
                    }
                    numberOfImages++;
                }
                if (numberOfImages == numberOfLinks)
                {
                    break;
                }
            }
            Titles(doc);
        }
        catch (Exception ex)
        {
            ErrorDialog("There was a problem in Image links.'n" + ex.Message);
        }
    }
    public void Titles(HtmlDocument doc)
    {
        try
        {
            //int a = 0;
            foreach (var link in doc.DocumentNode.Descendants("a").Where(t => t.Attributes.Contains("title")))
            {
                if (link != null && link.InnerText != "WatchFree.to" && link.InnerText != "Movies" && link.InnerText != "TV Shows")
                {
                    string x = link.GetAttributeValue("title", null);
                    x = x.Replace("Watch Putlocker", "");
                    x = x.Trim();
                    SearchTitles[numberOfTitles] = x;
                    numberOfTitles++;
                    if (numberOfTitles == numberOfLinks)
                    {
                        break;
                    }
                }
            }
            SearchList = SearchManager.GetTVShows(lastListItems, numberOfLinks);
            // += or =       we will find out
            this.Bindings.Update();
            lastListItems = numberOfLinks;
            CheckNextPageLinks(doc);
        }
        catch (Exception ex)
        {
            ErrorDialog("There was a problem while acquiring movie titles.'n" + ex.Message);
        }
    }
    private void SearchGrid_ItemClick(object sender, ItemClickEventArgs e)
    {
        var clickedItem = (SearchItems)e.ClickedItem;
        if (SearchImageLinks[clickedItem.SearchID - 1] != null && clickedItem.SearchLink != null)
        {
            if (clickedItem.SearchLink.Contains("tv-show"))
            {
                string[] itemDetails = { clickedItem.SearchTitle, SearchImageLinks[(clickedItem.SearchID - 1)], clickedItem.SearchLink };
                Frame.Navigate(typeof(TVShowDetailsPage), itemDetails);
            }
            else if (clickedItem.SearchLink.Contains("movie"))
            {
                string[] itemDetails = { clickedItem.SearchTitle, SearchImageLinks[(clickedItem.SearchID - 1)], clickedItem.SearchLink };
                Frame.Navigate(typeof(MovieDetails), itemDetails);
            }
        }
        else
        {
            ;
        }
    }
    private void SearchInputBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        string input = SearchInputBox.Text.Trim();
        string output = "";
        if (input.Length < 3)
        {
            SearchGridHeader.Text = "";
            if (SearchNextPagesLinks[0] != null || SearchLinks[0] != null || SearchImageLinks[0] != null || SearchTitles[0] != null)
            {
                DefaultVariablesValues();
            }
            if (SearchList != null)
            {
                if (SearchList.Count > 0)
                { 
                    DeleteList((SearchList.Count));
                }
            }
        }
        if (!(input.Length < 3))
        {
            //sTimer = new DispatcherTimer();
            if (!sTimer.IsEnabled)
            {
                sTimer.Interval = TimeSpan.FromSeconds(1);
                //sTimer.Start();
            }
            ErrorTextBox.Text = "";
            SearchGridHeader.Text = "Search Results";
            if (input.Contains(" "))
            {
                output = input.Replace(" ", "+");
                output = MoviesPage.MoviesBaseLink + @"/?keyword=" + output + @"&search_section=1";
                ErrorTextBox.Text = output;
                ErrorTextBox.IsTextSelectionEnabled = true;
            }
            else
            {
                output = MoviesPage.MoviesBaseLink + @"/?keyword=" + input + @"&search_section=1";
                //ErrorTextBox.Text = output;
            }
            SearchList = new ObservableCollection<SearchItems>();
            LoadHtmlDocument(output);
        }
        else
        {
            ErrorTextBox.Text = "the length of the input should not be less than 3";
            if (input.Length == 0)
            {
                ErrorTextBox.Text = "";
            }
            if (sTimer.IsEnabled)
                sTimer.Stop();
        }
    }
    private void IndexPageLink_Click(object sender, RoutedEventArgs e)
    {
        Frame.Navigate(typeof(IndexPage));
    }
    private void MoreItemsLink_Click(object sender, RoutedEventArgs e)
    {
        LoadHtmlDocument(MoviesPage.MoviesBaseLink + SearchNextPagesLinks[numberOfPages - 1]);
    }
    private void DefaultVariablesValues()
    {
        numberOfLinks = 0;
        numberOfTitles = 0;
        numberOfImages = 0;
        nextPage = 2;
        numberOfPages = 0;
        lastListItems = 0;
        int a = 0;
        foreach (var item in SearchLinks)
        {
            if (item != null)
            {
                SearchLinks[a] = null;
            }
            a++;
        }
        a = 0;
        foreach (var item in SearchTitles)
        {
            if (item != null)
            {
                SearchTitles[a] = null;
            }
            a++;
        }
        a = 0;
        foreach (var item in SearchImageLinks)
        {
            if (item != null)
            {
                SearchImageLinks[a] = null;
            }
            a++;
        }
        a = 0;
        foreach (var item in SearchNextPagesLinks)
        {
            if (item != null)
            {
                SearchNextPagesLinks[a] = null;
            }
            a++;
        }
    }
    private void CheckNextPageLinks(HtmlDocument doc)
    {
        string lastLink = "";
        foreach (var link in doc.DocumentNode.Descendants("a").Where(t => t.Attributes.Contains("href")))
        {
            string value = link.GetAttributeValue("href", "");
            if (value.StartsWith("/?keyword") && value.Contains("page=" + nextPage))
            {
                SearchNextPagesLinks[numberOfPages] = value;
                lastLink = value;
                numberOfPages++;
                break;
            }
        }
        //--------------------------------------
        // checking for the availability of next page
        if (lastLink.StartsWith(@"/?keyword") && lastLink.Contains("page=" + nextPage))
        {
            MoreItemsLink.Visibility = Visibility.Visible;
        }
        else
        {
            MoreItemsLink.Visibility = Visibility.Collapsed;
        }
        //--------------------------------------
        foreach (var item in SearchNextPagesLinks)
        {
            if (item == lastLink)
            {
                nextPage++;
            }
        }
    }
}
}

IncrementalLoadingInterface中的代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
namespace WatchfreeWebsite
{
public interface IIncrementalSource<T>
{
    Task<IEnumerable<T>> GetPagedItems(int pageIndex, int pageSize);
}
public class IncrementalLoadingCollection<T, I> : ObservableCollection<I>,
 ISupportIncrementalLoading
 where T : IIncrementalSource<I>, new()
{
    private T source;
    private int itemsPerPage;
    private bool hasMoreItems;
    private int currentPage;
    public IncrementalLoadingCollection(int itemsPerPage = 1)
    {
        this.source = new T();
        this.itemsPerPage = itemsPerPage;
        this.hasMoreItems = true;
    }
    public bool HasMoreItems
    {
        get { return hasMoreItems; }
    }
    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        var dispatcher = Window.Current.Dispatcher;
        return Task.Run(
            async () =>
            {
                uint resultCount = 0;
                var result = await source.GetPagedItems(currentPage++, itemsPerPage);
                if (result == null || result.Count() == 0)
                {
                    hasMoreItems = false;
                }
                else
                {
                    resultCount = (uint)result.Count();
                    await dispatcher.RunAsync(
                        CoreDispatcherPriority.Normal,
                        () =>
                        {
                            foreach (I item in result)
                                this.Add(item);
                        });
                }
                return new LoadMoreItemsResult() { Count = resultCount };
            }).AsAsyncOperation();
    }
}
}

SearchItems中的代码(单独的类):

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace WatchfreeWebsite
{
public class SearchItems
{
    public int SearchID
    {
        get; set;
    }
    public string SearchTitle
    {
        get; set;
    }
    public string SearchImageLink
    {
        get; set;
    }
    public string SearchLink { get; set; }
}
public class SearchManager : IIncrementalSource<SearchItems>
{
    private ObservableCollection<SearchItems> items;
    public async Task<IEnumerable<SearchItems>> GetPagedItems(int pageIndex, int pageSize)
    {
        return await Task.Run<IEnumerable<SearchItems>>(() =>
        {
            if (SearchPage.lastListItems == 0 && SearchPage.numberOfLinks == 0)
            {
                var shows = new ObservableCollection<SearchItems>();
                shows.Add(new SearchItems { SearchID = 1, SearchTitle = "No Search Results", SearchImageLink = @"ms-appx:///Assets/noposter.jpg" });
                return shows;
            }
            else
            {
                var result = GetTVShows(SearchPage.lastListItems, SearchPage.numberOfLinks); //(from p in persons select p).Skip(pageIndex * pageSize).Take(pageSize);
                return result;
            }
        });
    }
    public static ObservableCollection<SearchItems> GetTVShows(int start, int finish)
    {
        var movies = new ObservableCollection<SearchItems>();
        for (int x = start; x < finish; x++)
        {
            movies.Add(new SearchItems { SearchID = (x + 1), SearchTitle = SearchPage.SearchTitles[x], SearchImageLink = SearchPage.SearchImageLinks[x], SearchLink = SearchPage.SearchLinks[x] });
        }
        //if (start == 0 && finish == 0)
        {
            //movies.Add(new SearchItems { SearchID = 1, SearchTitle = "No Search Results", SearchImageLink = @"ms-appx:///Assets/noposter.jpg" });
        }
        return movies;
    }
}
}

解释:首先,在实现增量加载之前,我使用startfinish参数调用GetTVShows()以获得所需的项目数量。如果搜索没有得到任何东西,则它们都是zero,因此GetTVShows()只产生一个带有No Results的项目。

但是在增量加载中,我必须在编译时指定我想要多少项,因为它必须搜索项,我不能指定将有多少项,但每次请求获得的最大项是24项。

我甚至试图使用+=到我的SearchResults,但VS产生的错误,这是不可用的ObservableCollection,所以我搜索互联网,发现增量加载。但如果可能的话,我想通过点击链接来添加更多结果,而不是滚动页面边缘。我似乎无法理解增量加载是如何工作的,以及我需要如何调用我的GetTVShows()函数来产生所需的结果,就像现在一样。

我还记得Windows 10的Twitter,因为它使用增量加载来通过hyperlink点击获得更多的dm。但是这些dm已经存储在数据库中,所以它们不是动态添加的(至少这是我认为的,我可能是错的)。

如果有人能指出我能做些什么来让它工作,那将是非常感激的。任何帮助我的信息或任何链接指向我正确的方向,这样我就可以了解ISupportIncrementalLoading实际工作的效果,将不胜感激。谢谢。

实现isupportincrementloading接口- UWP - c#

我自己弄明白了…

public static ObservableCollection<SearchItems> GetTVShows(int start, int finish)
{
    var movies = new ObservableCollection<SearchItems>();
    for (int x = start; x < finish; x++)
    {
        movies.Add(new SearchItems { SearchID = (x + 1), SearchTitle = SearchPage.SearchTitles[x], SearchImageLink = SearchPage.SearchImageLinks[x], SearchLink = SearchPage.SearchLinks[x] });
    }
    if (start == 0 && finish == 0)
    {
        movies.Add(new SearchItems { SearchID = 1, SearchTitle = "No Search Results", SearchImageLink = @"ms-appx:///Assets/noposter.jpg" });
    }
    return movies;
}

我使用上面的代码将项目添加到我的GridView中,结果发现var movies在局部作用域中,所以每次调用函数时它都是空的。这就是为什么它只装载了被要求的物品。现在我在文件作用域中将其声明为private static,因为GetTVShows()也是一个静态函数,当我单击hyperlink按钮时,它会向视图添加更多项。

所以在我的例子中,所有花在增量加载上的时间都是浪费的。因为我不需要边递增加载

现在我的代码看起来像:
private static ObservableCollection<SearchItems> movies = new ObservableCollection<SearchItems>();
public static ObservableCollection<SearchItems> GetTVShows(int start, int finish)
{
//var movies = new ObservableCollection<SearchItems>();
for (int x = start; x < finish; x++)
{
    movies.Add(new SearchItems { SearchID = (x + 1), SearchTitle = SearchPage.SearchTitles[x], SearchImageLink = SearchPage.SearchImageLinks[x], SearchLink = SearchPage.SearchLinks[x] });
}
if (start == 0 && finish == 0)
{
    movies.Add(new SearchItems { SearchID = 1, SearchTitle = "No Search Results", SearchImageLink = @"ms-appx:///Assets/noposter.jpg" });
}
return movies;
}

希望它能帮助别人一路走来…