我正在学习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()
说明:
首先在实施增量加载之前,我使用start
和finish
参数调用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>
实际工作方式的效果,将会受到很多赞赏。感谢。
答案 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;
}
希望它能帮助其他人...