私はC#を学んでいて、現在UWPアプリでISupportIncrementalLoading
に取り組んでいますが、傾けることはできません。コンパイルする前からエラーが出ます。私はhereからアイディアを得ました。しかし、私は自分のアプリケーションでそれをどのように実装できるのか理解できません。ISupportIncrementalLoadingインターフェイスを実装する - UWP - C#
私はIIncrementalLoading
インターフェイスと、ObservableCollection<T>
にコンテンツを動的に追加する別のクラスを持っています。 Incremental Loading
を実装していない場合、私のObservableCollection
はSearchPage.xaml
に動的にコンテンツを提供します.にはコンテンツが追加されますが、以前に生成されたアイテムが置き換えられ、代わりに新しいアイテムのみが表示されます。 SearchPage.xaml
で
コード:SearchPage.xaml.cs
で
<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>
コード:IncrementalLoadingInterface
で
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++;
}
}
}
}
}
コード:
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();
}
}
}
(別のクラス)で
コード:
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
で1つのアイテムのみを生成します。
インクリメンタルロードでは、コンパイル時に必要なアイテムの数を指定する必要があります。アイテムを検索する必要があるため、アイテム数は指定できませんが、最大アイテム数は24です。
私もSearchResults
に+=
を使用しようとしましたが、VSはこれがObservableCollection
で利用できないというエラーを生成するため、インターネットを検索してインクリメンタルロードを検出しました。しかし、可能であれば、エッジをスクロールするのではなく、リンクをクリックして結果を追加したいと思っています。インクリメンタルロードがどのように機能しているのか、私のGetTVShows()
関数を呼び出す必要があるので、現在のように望ましい結果が得られるとは思えません。
私はhyperlink
クリックでさらに多くのDMを取得するためにインクリメンタルロードを使用しているので、これはWindows 10用のTwitterからもリコールされています。しかし、それらのDMは既にデータベースに格納されているので、動的に追加されません(少なくとも私が思うものであり、間違っている可能性があります)。
誰かが私がそれを動作させるためにできることを指摘できれば、それは本当に感謝しています。どのように私が正しい方向に私を指すように私を助けるためのあらゆる情報、またはISupportIncrementalLoading
が実際にどのように働くかの影響を理解することができます。ありがとう。