实现ISupportIncrementalLoading接口 - UWP - C#

时间:2016-11-09 07:58:01

标签: c# xaml uwp

我正在学习C#并且目前正在使用UWP应用程序中的ISupportIncrementalLoading,但似乎无法掌握它。它甚至在编译之前就给我错误。我从here得到了这个想法。但我无法理解如何在我的应用程序中实现它。

我有一个IIncrementalLoading接口和一个单独的类,可以动态地将内容添加到ObservableCollection<T>。如果我没有实施Incremental Loading我的ObservableCollection动态地向SearchPage.xaml GridView中的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; } } } 中的代码(单独的类):

GetTVShows()

说明: 首先在实施增量加载之前,我使用startfinish参数调用zero以获取所需的项目数量。如果搜索没有得到任何内容,则两者都为GetTVShows(),因此No Results只生成一个+=项。

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

我甚至尝试将SearchResults用于我的ObservableCollection,但VS会产生GetTVShows()无法使用的错误,因此我搜索了互联网并找到了增量加载。但如果可能,我想通过点击链接添加更多结果,而不是滚动边缘。我似乎无法理解增量加载是如何工作的以及我如何调用我的hyperlink函数来生成所需的结果,就像现在一样。

我还从Twitter for Windows 10中回忆起这一点,因为它使用增量加载来获得更多带有ISupportIncrementalLoading点击的DM。但是那些DM已经存储在数据库中,因此它们不会被动态添加(至少这是我认为的,我可能是错的。)。

如果有人可以指出我能做些什么来使其发挥作用,那将非常感激。任何帮助我的信息或指向正确方向的任何链接,以便我能理解<ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" android:scrollbars="none"> <RelativeLayout android:id="@+id/SU_user_detail_parent_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/custom_background"> <More Components here..../> </RelativeLayout> </ScrollView> 实际工作方式的效果,将会受到很多赞赏。感谢。

1 个答案:

答案 0 :(得分:1)

我自己想出来了......

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

希望它能帮助其他人...