实现isupportincrementloading接口- UWP - c#
本文关键字:UWP 接口 isupportincrementloading 实现 | 更新日期: 2023-09-27 18:17:15
我正在学习c#,目前正在UWP应用程序中研究ISupportIncrementalLoading
,但似乎无法掌握它。它甚至在编译之前就给了我错误。我从这里得到了灵感。但是我无法理解如何在我的应用程序中实现它。
我有一个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;
}
}
}
解释:首先,在实现增量加载之前,我使用start
和finish
参数调用GetTVShows()
以获得所需的项目数量。如果搜索没有得到任何东西,则它们都是zero
,因此GetTVShows()
只产生一个带有No Results
的项目。
但是在增量加载中,我必须在编译时指定我想要多少项,因为它必须搜索项,我不能指定将有多少项,但每次请求获得的最大项是24项。
我甚至试图使用+=
到我的SearchResults
,但VS产生的错误,这是不可用的ObservableCollection
,所以我搜索互联网,发现增量加载。但如果可能的话,我想通过点击链接来添加更多结果,而不是滚动页面边缘。我似乎无法理解增量加载是如何工作的,以及我需要如何调用我的GetTVShows()
函数来产生所需的结果,就像现在一样。
我还记得Windows 10的Twitter,因为它使用增量加载来通过hyperlink
点击获得更多的dm。但是这些dm已经存储在数据库中,所以它们不是动态添加的(至少这是我认为的,我可能是错的)。
如果有人能指出我能做些什么来让它工作,那将是非常感激的。任何帮助我的信息或任何链接指向我正确的方向,这样我就可以了解ISupportIncrementalLoading
实际工作的效果,将不胜感激。谢谢。
我自己弄明白了…
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;
}
希望它能帮助别人一路走来…