Module 5 - Creating the UI

This module is an alternative way of creating the UI from C# Markup without importing it from Figma.

It includes the C# Markup building blocks that are used in our app if you decide to skip module 4 and import it from Figma.

Import MainPage

Replace the contents of MainPage.cs with the following:

MainPage.cs code contents (collapsed for brevity)
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using Microsoft.UI.Xaml.Navigation;
using System;
using Uno.Extensions.Markup;
using Uno.Extensions.Navigation.UI;
using Uno.Material;
using Uno.Toolkit.UI;

namespace TubePlayer.Presentation;

public partial class MainPage : Page
{
    public MainPage()
    {
        this.DataContext<MainViewModel>((page, vm) => page
            .Background(Theme.Brushes.Background.Default)
            .NavigationCacheMode(NavigationCacheMode.Required)
            .StatusBar
            (
                s => s
                    .Foreground(StatusBarForegroundTheme.Auto)
                    .Background(Theme.Brushes.Surface.Default)
            )
            .Resources
            (
                r => r
                    .Add("Icon_Chevron_Right", "F1 M 1.4099998474121094 0 L 0 1.4099998474121094 L 4.579999923706055 6 L 0 10.59000015258789 L 1.4099998474121094 12 L 7.409999847412109 6 L 1.4099998474121094 0 Z")
                    .Add("Icon_Search", "F1 M 12.5 11 L 11.710000038146973 11 L 11.430000305175781 10.729999542236328 C 12.410000324249268 9.589999556541443 13 8.110000014305115 13 6.5 C 13 2.9100000858306885 10.089999914169312 0 6.5 0 C 2.9100000858306885 0 0 2.9100000858306885 0 6.5 C 0 10.089999914169312 2.9100000858306885 13 6.5 13 C 8.110000014305115 13 9.589999556541443 12.410000324249268 10.729999542236328 11.430000305175781 L 11 11.710000038146973 L 11 12.5 L 16 17.489999771118164 L 17.489999771118164 16 L 12.5 11 L 12.5 11 Z M 6.5 11 C 4.009999990463257 11 2 8.990000009536743 2 6.5 C 2 4.009999990463257 4.009999990463257 2 6.5 2 C 8.990000009536743 2 11 4.009999990463257 11 6.5 C 11 8.990000009536743 8.990000009536743 11 6.5 11 Z")
            )
            .Content
            (
                new AutoLayout()
                    .PrimaryAxisAlignment(AutoLayoutAlignment.Center)
                    .VerticalAlignment(VerticalAlignment.Stretch)
                    .HorizontalAlignment(HorizontalAlignment.Center)
                    .Width(400)
                    .Children
                    (
                        new NavigationBar()
                            .Width(400)
                            .AutoLayout(counterAlignment: AutoLayoutAlignment.Center)
                            .Content
                            (
                                new AutoLayout()
                                    .PrimaryAxisAlignment(AutoLayoutAlignment.Center)
                                    .Orientation(Orientation.Horizontal)
                                    .Children
                                    (
                                        new Image()
                                            .Source(new BitmapImage(new Uri("https://picsum.photos/384/40")))
                                            .Stretch(Stretch.UniformToFill)
                                            .AutoLayout(primaryAlignment: AutoLayoutPrimaryAlignment.Stretch)
                                    )
                            ),
                        new AutoLayout()
                            .Background(Theme.Brushes.Surface.Default)
                            .Padding(12)
                            .Children
                            (
                                new TextBox()
                                    .Background(Theme.Brushes.Surface.Variant.Default)
                                    .Text(b => b.Binding(() => vm.SearchTerm).TwoWay().UpdateSourceTrigger(UpdateSourceTrigger.PropertyChanged))
                                    .PlaceholderText("Search")
                                    .CornerRadius(20)
                                    .BorderThickness(0)
                                    .Style(Theme.TextBox.Styles.Outlined)
                                    .ControlExtensions
                                    (
                                        icon:
                                            new PathIcon()
                                                .Data(StaticResource.Get<Geometry>("Icon_Search"))
                                                .Foreground(Theme.Brushes.OnSurface.Variant.Default)
                                    )
                            ),
                        new ListView()
                            .Background(Theme.Brushes.Background.Default)
                            .ItemsSource(() => vm.VideoSearchResults)
                            .Padding(12, 8)
                            .Navigation(request: "VideoDetails")
                            .AutoLayout(primaryAlignment: AutoLayoutPrimaryAlignment.Stretch)
                            .ItemTemplate<YoutubeVideo>
                            (
                                youtubeVideo =>
                                    new CardContentControl()
                                        .Margin(0, 0, 0, 8)
                                        .Style(StaticResource.Get<Style>("ElevatedCardContentControlStyle"))
                                        .Content
                                        (
                                            new AutoLayout()
                                                .Background(Theme.Brushes.Surface.Default)
                                                .CornerRadius(12)
                                                .PrimaryAxisAlignment(AutoLayoutAlignment.Center)
                                                .Children
                                                (
                                                    new AutoLayout()
                                                        .Background(Theme.Brushes.Surface.Default)
                                                        .CornerRadius(12)
                                                        .Padding(8, 8, 8, 0)
                                                        .MaxHeight(288)
                                                        .MaxWidth(456)
                                                        .AutoLayout(counterAlignment: AutoLayoutAlignment.Center)
                                                        .Children
                                                        (
                                                            new Border()
                                                                .Height(204.75)
                                                                .CornerRadius(6)
                                                                .Child
                                                                (
                                                                    new Image()
                                                                        .Source(() => youtubeVideo.Details.Snippet?.Thumbnails?.Medium?.Url!)
                                                                        .Stretch(Stretch.UniformToFill)
                                                                ),
                                                            new AutoLayout()
                                                                .Spacing(8)
                                                                .Orientation(Orientation.Horizontal)
                                                                .Padding(0, 8)
                                                                .Children
                                                                (
                                                                    new Border()
                                                                        .Width(60)
                                                                        .Height(60)
                                                                        .CornerRadius(6)
                                                                        .AutoLayout(counterAlignment: AutoLayoutAlignment.Center)
                                                                        .Child
                                                                        (
                                                                            new Image()
                                                                                        .Source(() => youtubeVideo.Channel.Snippet?.Thumbnails?.Medium?.Url!)
                                                                                .Stretch(Stretch.UniformToFill)
                                                                        ),
                                                                    new AutoLayout()
                                                                        .PrimaryAxisAlignment(AutoLayoutAlignment.Center)
                                                                        .AutoLayout(primaryAlignment: AutoLayoutPrimaryAlignment.Stretch)
                                                                        .Children
                                                                        (
                                                                            new TextBlock()
                                                                                .Text(() => youtubeVideo.Channel.Snippet?.Title)
                                                                                .Height(22)
                                                                                .Foreground(Theme.Brushes.OnSurface.Default)
                                                                                .Style(Theme.TextBlock.Styles.TitleMedium),
                                                                            new TextBlock()
                                                                                .Text(() => youtubeVideo.Details.Snippet?.Title)
                                                                                .Height(16)
                                                                                .Foreground(Theme.Brushes.OnSurface.Medium)
                                                                        ),
                                                                    new Button()
                                                                        .Foreground(Theme.Brushes.OnSurface.Variant.Default)
                                                                        .Style(Theme.Button.Styles.Icon)
                                                                        .AutoLayout(counterAlignment: AutoLayoutAlignment.Center)
                                                                        .Content
                                                                        (
                                                                            new PathIcon()
                                                                                .Data(StaticResource.Get<Geometry>("Icon_Chevron_Right"))
                                                                                .Foreground(Theme.Brushes.OnSurface.Variant.Default)
                                                                        )
                                                                )
                                                        )
                                                )
                                        )
                            )
                    )
            ))
            ;
    }
}

Import VideoDetailsPage

Replace the contents of VideoDetailsPage.cs with the following:

VideoDetailsPage.cs code contents (collapsed for brevity)
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using Uno.Extensions.Markup;
using Uno.Toolkit.UI;

namespace TubePlayer.Presentation;

public partial class VideoDetailsPage : Page
{
    public VideoDetailsPage()
    {
        this.DataContext<VideoDetailsViewModel>((page, vm) => page
            .Background(Theme.Brushes.Background.Default)
            .NavigationCacheMode(NavigationCacheMode.Required)
            .StatusBar
            (
                s => s
                    .Foreground(StatusBarForegroundTheme.Auto)
                    .Background(Theme.Brushes.Surface.Default)
            )
            .Resources
            (
                r => r
                    .Add("Icon_Arrow_Back", "F1 M 16 7 L 3.8299999237060547 7 L 9.420000076293945 1.4099998474121094 L 8 0 L 0 8 L 8 16 L 9.40999984741211 14.59000015258789 L 3.8299999237060547 9 L 16 9 L 16 7 Z")
            )
            .Content
            (
                new AutoLayout()
                    .Background(Theme.Brushes.Background.Default)
                    .Children
                    (
                        new AutoLayout()
                            .Width(400)
                            .AutoLayout
                            (
                                counterAlignment: AutoLayoutAlignment.Center,
                                primaryAlignment: AutoLayoutPrimaryAlignment.Stretch
                            )
                            .Children
                            (
                                new NavigationBar()
                                    .HorizontalContentAlignment(HorizontalAlignment.Left)
                                    .Content("Video")
                                    .MainCommand
                                    (
                                        new AppBarButton()
                                            .Icon
                                            (
                                                new PathIcon()
                                                    .Data(StaticResource.Get<Geometry>("Icon_Arrow_Back"))
                                                    .Foreground(Theme.Brushes.OnSurface.Default)
                                            )
                                    ),
                                new MediaPlayerElement()
                                    .AreTransportControlsEnabled(true)
                                    .Width(400)
                                    .Height(300)
                                    .AutoLayout(counterAlignment: AutoLayoutAlignment.Start)
                                    .TransportControls
                                    (
                                        new MediaTransportControls()
                                            .IsCompact(true)
                                    ),
                                new ScrollViewer()
                                    .AutoLayout(primaryAlignment: AutoLayoutPrimaryAlignment.Stretch)
                                    .Content
                                    (
                                        new AutoLayout()
                                            .Children
                                            (
                                                new AutoLayout()
                                                    .Spacing(6)
                                                    .Padding(16)
                                                    .Width(400)
                                                    .AutoLayout(counterAlignment: AutoLayoutAlignment.Start)
                                                    .Children
                                                    (
                                                        new TextBlock()
                                                            .TextWrapping(TextWrapping.Wrap)
                                                            .Text(() => vm.Video.Channel.Snippet?.Title)
                                                            .Foreground(Theme.Brushes.OnSurface.Default)
                                                            .Style(Theme.TextBlock.Styles.TitleLarge),
                                                        new TextBlock()
                                                            .Text(() => vm.Video.FormattedStatistics)
                                                            .Foreground(Theme.Brushes.OnSurface.Medium)
                                                            .AutoLayout(counterAlignment: AutoLayoutAlignment.Start)
                                                    ),
                                                new AutoLayout()
                                                    .Spacing(8)
                                                    .Orientation(Orientation.Horizontal)
                                                    .Padding(16, 8)
                                                    .Width(400)
                                                    .AutoLayout(counterAlignment: AutoLayoutAlignment.Start)
                                                    .Children
                                                    (
                                                        new Border()
                                                            .Width(40)
                                                            .Height(40)
                                                            .CornerRadius(20)
                                                            .AutoLayout(counterAlignment: AutoLayoutAlignment.Center)
                                                            .Child
                                                            (
                                                                new Image()
                                                                    .Source(() => vm.Video.Channel.Snippet?.Thumbnails?.High?.Url!)
                                                                    .Stretch(Stretch.UniformToFill)
                                                            ),
                                                        new AutoLayout()
                                                            .Spacing(2)
                                                            .PrimaryAxisAlignment(AutoLayoutAlignment.Center)
                                                            .Height(37)
                                                            .AutoLayout
                                                            (
                                                                counterAlignment: AutoLayoutAlignment.Center,
                                                                primaryAlignment: AutoLayoutPrimaryAlignment.Stretch
                                                            )
                                                            .Children
                                                            (
                                                                new AutoLayout()
                                                                    .Orientation(Orientation.Horizontal)
                                                                    .AutoLayout
                                                                    (
                                                                        counterAlignment: AutoLayoutAlignment.Start,
                                                                        primaryAlignment: AutoLayoutPrimaryAlignment.Stretch
                                                                    )
                                                                    .Children
                                                                    (
                                                                        new TextBlock()
                                                                            .Text(() => vm.Video.FormattedSubscriberCount)
                                                                            .Foreground(Theme.Brushes.OnSurface.Medium)
                                                                            .AutoLayout(counterAlignment: AutoLayoutAlignment.Start)
                                                                    ),
                                                                new TextBlock()
                                                                    .Text(() => vm.Video.Channel.Snippet?.Title)
                                                                    .Foreground(Theme.Brushes.OnSurface.Default)
                                                                    .Style(Theme.TextBlock.Styles.TitleMedium)
                                                                    .AutoLayout(counterAlignment: AutoLayoutAlignment.Start)
                                                            )
                                                    ),
                                                new TextBlock()
                                                    .TextWrapping(TextWrapping.Wrap)
                                                    .Text(() => vm.Video.Channel.Snippet?.Description)
                                                    .Margin(16)
                                                    .Foreground(Theme.Brushes.OnSurface.Variant.Default)
                                                    .Style(Theme.TextBlock.Styles.BodySmall)
                                                    .AutoLayout(counterAlignment: AutoLayoutAlignment.Start)
                                    )
                            )
                    )
            )));
    }
}

Run the app

Run the app (F5 on Visual Studio) and observe the UI changes, it should look similar to the following:

UI output of the first page

If you try tapping one of the videos in the list, an exception will occur. This is because navigation has not yet been implemented. You will address that in Module 7 - Navigation.
The image above the search page is a random image. It will be replaced in Module 11 - App finalization

Next Step

In the next step, you will adjust the UI you've imported by overriding the app's color theme.

Previous | Next