uid |
---|
Workshop.TubePlayer.MockData |
In this module, you will create models and services that will be used by the presentation layer to retrieve data and display it in the appropriate UI controls. You are first going to add a mock service that will simulate YouTube search results. In module 9, you will wire the service up with live search results from YouTube's API.
[!INCLUDE Create entities]
In the Business folder, add a class named YoutubeServiceMockData.cs, and replace its content with the following:
YoutubeServiceMockData.cs code contents (collapsed for brevity)
[!code-csharpYoutubeServiceMockData.cs]
This class contains two constant variables that are assigned to partial JSON output results taken from a real YouTube search query of the term 'Uno Platform'.
-
In the same folder (Business), create a new interface file named IYoutubeService.cs, that will represent our data service. Ignore errors you might see while editing the following files, these will addressed soon by adding the missing namespaces globally.
namespace TubePlayer.Business; public interface IYoutubeService { Task<YoutubeVideoSet> SearchVideos(string searchQuery, string nextPageToken, uint maxResult, CancellationToken ct); }
-
Add another class named YoutubeServiceMock.cs to the Business folder and replace its content with the following:
YoutubeServiceMock.cs code contents (collapsed for brevity)
[!code-csharpYoutubeServiceMock.cs]
The SearchVideos
method reads the JSON result you added in the previous instruction and deserializes it into ChannelSearchResultData
and VideoDetailsResultData
objects respectively.
As we've selected Dependency Injection when generating the app, it includes full DI support on all platforms.
You will now register the YoutubeServiceMock
to be provided every time an IYoutubeService
is requested.
-
Open GlobalUsings.cs and append the following lines to it:
global using System.Text.Json; global using TubePlayer.Business; global using TubePlayer.Services.Models;
In Visual Studio, you can sort the usings, go to the menu and click Edit → IntelliSense → Sort Usings (Alt+E,I,S).
-
Open the App.xaml.cs file (in the project folder), head to the
ConfigureServices
section, remove the comments in it, and add the following registrations instead:services.AddSingleton<IYoutubeService, YoutubeServiceMock>();
-
Before the line
.ConfigureServices
add the following service registration:.UseSerialization(services => { services.AddSingleton(new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); })
This sets up Uno Platform's serialization extension.
-
Open the file MainModel.cs and replace its content with the following:
namespace TubePlayer.Presentation; public partial record MainModel(IYoutubeService YoutubeService) { public IState<string> SearchTerm => State<string>.Value(this, () => "Uno Platform"); }
The
SearchTerm
is an MVUX state, with "Uno Platform" set as its default value. Feeds and states are part of the MVUX framework developed by Uno Platform.
Both feeds and states are used as an async data connection point between the model and its underlying services. The MVUX also offers controls that can interact with feeds and states.
The difference between states and feeds is that a state holds the state of the data and can be updated manually, whereas feeds only act as a bridge to the data coming from the service.To learn more about MVUX, refer to the MVUX docs.
-
After the
SearchTerm
property, add another property. Contrary to theSearchTerm
which is a state to support two-way binding to and from the searchTextBox
, theVideoSearchResults
property we are now adding will be a list-feed (a feed of a collection of items) that requests and obtains the search results we just set up in the mock service.public IListFeed<YoutubeVideo> VideoSearchResults => SearchTerm .Where(searchTerm => searchTerm is { Length: > 0 }) .SelectAsync(async (searchTerm, ct) => await YoutubeService.SearchVideos(searchTerm, nextPageToken: string.Empty, maxResult: 30, ct)) .Select(result => result.Videos) .AsListFeed();
-
Go back to MainPage.cs and set the
Page
'sDataContext
to the generated bindable proxy ofMainModel
, by adding the following line to the beginning of the UI tree (afterthis.
).+this.DataContext<BindableMainModel>((page, vm) => page .NavigationCacheMode(NavigationCacheMode.Required) ...
-
Add a closing parenthesis at the end of the C# Markup tree of
MainModel
to close that (you can just add another closing parenthesis before the terminating semicolon (;
). -
Bind the
TextBox
to theSearchTerm
state property, and expand theListView
's template like the following:[!code-csharpMainPage.cs]
The
DataTemplate
is set for aYoutubeVideo
object. It consists of aStackPanel
containing two text fields for the video title (styled in bold text), and the title of the YouTube channel that published the video.
-
Open the VideoDetailsModel.cs file, add a
YoutubeVideo
property instead ofEntity
, as well as theVideoSource
property. Here are the updated contents of the file:using Windows.Media.Core; namespace TubePlayer.Presentation; public partial record VideoDetailsModel(YoutubeVideo Video) { public IFeed<MediaSource> VideoSource => Feed.Async((ct) => new ValueTask<MediaSource>()); }
These properties are currently defined as placeholders to enable bindings to work properly but will be implemented to play YouTube videos in module 10.
-
In the VideoDetailsPage.cs, remove the
Text
extension method for now, as its binding depends on theEntity
property we've just removed.new TextBlock() - .Text(() => vm.Entity.Name) .HorizontalAlignment(HorizontalAlignment.Center) ...
-
You can now close all open tabs. In Visual Studio, this can be achieved by right-clicking any tab and clicking on Close All Tabs.
-
Run the app.
TheListView
will bind with the list-feed which will retrieve the JSON results from the service, based on the search term, which defaults to 'Uno Platform'. -
Try changing the search term. Let's see what we have for XAML (note that this is based on our limited JSON data):
In the next step, you're going to build the UI.
The UI for the Tube Player app has been designed using Figma - an app design tool, along with its Uno Platform plugin for Figma.
Previous | Next
Note
The next module exports the design from Figma. If you don't want to use Figma, you can skip the next module and go directly to Module 5, which provides the final C# Markup exported from Figma with some minor adjustments.