In the AutoComplete control, data binding can be done with both, static and dynamic, data source. This indicates that data binding can either be performed using C1DataCollection library or by simply binding the AutoComplete to any enumerable list of object.
To bind static data source to AutoComplete, say an enumerable list, you need to set the ItemsSource and type of the type parameter T for C1AutoComplete component. For more information on how to bind the ListView control programmatically with an enumerable list, see Quick Start topic.
The AutoComplete control supports binding with dynamic data source by means of C1DataCollection. The following example loads YouTube videos by changing the list source dynamically as the user types.
C# |
コードのコピー
|
---|---|
using System; using System.Collections.Generic; using System.Globalization; using System.Net.Http; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Threading; using System.Threading.Tasks; using C1.DataCollection; namespace Binding { public class YouTubeDataCollection : C1CursorDataCollection<YouTubeVideo> { private string _q; private string _orderBy = "relevance"; public YouTubeDataCollection() { PageSize = 20; } public int PageSize { get; set; } public override bool HasMoreItems { get { return _q != null && base.HasMoreItems; } } private SemaphoreSlim _searchSemaphore = new SemaphoreSlim(1); public async Task SearchAsync(string q) { //フィルタ文字列を設定し、遅延時間を待ちます。 _q = q; try { await _searchSemaphore.WaitAsync(); if (_q != q)//文字列が変更された場合は、別のキーストロークがあったことを意味します。 return; await RefreshAsync(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } finally { _searchSemaphore.Release(); } } public async Task OrderAsync(string orderBy) { _orderBy = orderBy; if (_q != null) await RefreshAsync(); } protected override async Task<Tuple<string, IReadOnlyList<YouTubeVideo>>> GetPageAsync(int startingIndex, string pageToken, int? count = null, IReadOnlyList<SortDescription> sortDescriptions = null, FilterExpression filterExpresssion = null, CancellationToken cancellationToken = default(CancellationToken)) { return await LoadVideosAsync(_q, "date", pageToken, PageSize, cancellationToken); } public static async Task<Tuple<string, IReadOnlyList<YouTubeVideo>>> LoadVideosAsync(string q, string orderBy, string pageToken, int maxResults, CancellationToken cancellationToken = default(CancellationToken)) { if (string.IsNullOrWhiteSpace(q)) return new Tuple<string, IReadOnlyList<YouTubeVideo>>(default, new YouTubeVideo[0]); var youtubeUrl = string.Format("https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q={0}&order={1}&maxResults={2}{3}&key={4}", Uri.EscapeUriString(q), orderBy, maxResults, string.IsNullOrWhiteSpace(pageToken) ? "" : "&pageToken=" + pageToken, "AIzaSyCtwKIq-Td5FBNOlvOiWEJaClRBDyq-ZsU"); var client = new HttpClient(); var response = await client.GetAsync(youtubeUrl, cancellationToken); if (response.IsSuccessStatusCode) { var videos = new List<YouTubeVideo>(); var serializer = new DataContractJsonSerializer(typeof(YouTubeSearchResult)); var result = serializer.ReadObject(await response.Content.ReadAsStreamAsync()) as YouTubeSearchResult; foreach (var item in result.Items) { var video = new YouTubeVideo() { Title = item.Snippet.Title, Description = item.Snippet.Description, Thumbnail = item.Snippet.Thumbnails.Default.Url, Link = "http://www.youtube.com/watch?v=" + item.Id.VideoId, ChannelTitle = item.Snippet.ChannelTitle, PublishedAt = DateTime.Parse(item.Snippet.PublishedAt), }; videos.Add(video); } return new Tuple<string, IReadOnlyList<YouTubeVideo>>(result.NextPageToken, videos); } else { throw new Exception(await response.Content.ReadAsStringAsync()); } } } [DataContract] public class YouTubeSearchResult { [DataMember(Name = "nextPageToken")] public string NextPageToken { get; set; } [DataMember(Name = "items")] public YouTubeSearchItemResult[] Items { get; set; } } [DataContract] public class YouTubeSearchItemResult { [DataMember(Name = "id")] public YouTubeVideoId Id { get; set; } [DataMember(Name = "snippet")] public YouTubeSnippet Snippet { get; set; } } [DataContract] public class YouTubeVideoId { [DataMember(Name = "videoId")] public string VideoId { get; set; } } [DataContract] public class YouTubeSnippet { [DataMember(Name = "title")] public string Title { get; set; } [DataMember(Name = "description")] public string Description { get; set; } [DataMember(Name = "thumbnails")] public YouTubeThumbnails Thumbnails { get; set; } [DataMember(Name = "channelTitle")] public string ChannelTitle { get; set; } [DataMember(Name = "publishedAt")] public string PublishedAt { get; set; } } [DataContract] public class YouTubeThumbnails { [DataMember(Name = "default")] public YouTubeThumbnail Default { get; set; } [DataMember(Name = "medium")] public YouTubeThumbnail Medium { get; set; } [DataMember(Name = "high")] public YouTubeThumbnail High { get; set; } } [DataContract] public class YouTubeThumbnail { [DataMember(Name = "url")] public string Url { get; set; } } [DataContract] public class YouTubeVideo { public string Title { get; set; } public string Description { get; set; } public string Thumbnail { get; set; } public string Link { get; set; } public string ChannelTitle { get; set; } public DateTime PublishedAt { get; set; } public string PublishedDay { get { var today = DateTime.Today; var publishedDate = PublishedAt.Date; var firstDayOfThisWeek = today.AddDays(CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek - today.DayOfWeek); var firstDayOfLastWeek = firstDayOfThisWeek - TimeSpan.FromDays(7); var firstDayOfTwoWeeksAgo = firstDayOfThisWeek - TimeSpan.FromDays(14); var firstDayOfThreeWeeksAgo = firstDayOfThisWeek - TimeSpan.FromDays(21); var firstDayOfThisMonth = new DateTime(today.Year, today.Month, 1); var firstDayOfLastMonth = today.Month == 1 ? new DateTime(today.Year - 1, 12, 1) : new DateTime(today.Year, today.Month - 1, 1); if (publishedDate == today) { return "Today"; } else if (today.Subtract(publishedDate).TotalDays == 1) { return "Yesterday"; } else if (publishedDate >= firstDayOfThisWeek) { return publishedDate.DayOfWeek.ToString(); } else if (publishedDate >= firstDayOfLastWeek) { return "Last Week"; } else if (publishedDate >= firstDayOfTwoWeeksAgo) { return "Two Weeks Ago"; } else if (publishedDate >= firstDayOfThreeWeeksAgo) { return "Three Weeks Ago"; } else if (publishedDate >= firstDayOfThisMonth) { return "This Month"; } else if (publishedDate >= firstDayOfLastMonth) { return "Last Month"; } else if (publishedDate >= new DateTime(today.Year, 1, 1)) { return "This Year"; } else if (publishedDate >= new DateTime(today.Year - 1, 1, 1)) { return "Last Year"; } else if (publishedDate >= new DateTime(today.Year - 1, 1, 1)) { return "Two Years Ago"; } else { return "Older"; } } } } } |
Razor |
コードのコピー
|
---|---|
@using C1.DataCollection @using C1.Blazor.Input <C1AutoComplete ItemsSource="_collection" T="YouTubeVideo" DisplayMemberPath="Title" Placeholder="@FlexGridRes.SearchPlaceholderText" Delay="@TimeSpan.FromSeconds(1)" Style="@("margin:8px 0;width:400px")" ListItemStyle="@("height:61px")" DropDownStyle="@("max-width:50vw;max-height:60vh")" Filtering="OnFiltering" ShowButton="false"> <ItemTemplate> <img src="@context.Thumbnail" style="height:45px;width:60px" /> <span style="margin-left:8px;white-space:nowrap;word-break:break-all">@context.Title</span> </ItemTemplate> </C1AutoComplete> @code{ YouTubeDataCollection _youTubeFeed; C1GroupDataCollection<YouTubeVideo> _collection; protected override async Task OnInitializedAsync() { _youTubeFeed = new YouTubeDataCollection(); var collection = new C1GroupDataCollection<YouTubeVideo>(_youTubeFeed, false); await collection.GroupAsync("PublishedDay"); _collection = collection; } async void OnFiltering(object sender, AutoCompleteFilteringEventArgs e) { var autoComplete = sender as C1AutoComplete<YouTubeVideo>; var deferal = e.GetDeferral(); try { await _youTubeFeed.SearchAsync(e.FilterString); e.Cancel = true; } finally { deferal.Complete(); } } } |