Skip to content

Proposal: default project improvements #10388

@sonnemaf

Description

@sonnemaf

Proposal: default project improvements

Summary

The current project template for a WinUI3 app is lacking a lot of issues. I recently created a new project which I wanted to use for a demo. It is strange that I had to add so many things before I could use it. These should be out of the box.

In this proposal I will show all the things I think are missing or wrong in the current template.

Scope

ID Capability Priority
1 Visual Assets - Place the Visual Assets in a Tiles subfolder folder of the Assets folder Must
2 Visual Assets - Remove unused tiles Must
3 Visual Assets - Add an Icon.ico and set it on the Window Must
4 MainWindow - Add MicaBackdrop Must
5 MainWindow - Add the new TitleBar Must
6 MainWindow - Add a Minimum size Must
7 MainWindow - Replace the 'Click Me' Button for a Frame and navigate to a MainPage Must
8 Introduce a MainPage with a Counter Should
9 Folders - Add a GlobalUsings.cs Could
10 Folders - Introduce a Views folder Could
11 Folders - Default Styles.xaml Resource Dictionary Should
12 Folders - Default Themes.xaml Resource Dictionary Should
  • 'Must' implies that the feature should not ship without this capability.
  • 'Should' is something we should push hard for, but is not absolutely required to ship.
  • 'Could' is a nice-to-have; a good stretch goal that isn't painful if we don't achieve it.
  • 'Won't' is a clear statement that the proposal/feature will intentionally not have that capability.

Visual Assets

Place the Visual Assets in a Tiles subfolder folder of the Assets folder

Currently all tiles are placed in the Assets folder itself. I often create extra folders too like Fonts, Sounds, Images but they don't have to be there in the template.

The Package.appxmanifest should point to this folder.

Image

Remove unused tiles

The Wide310x150Logo.png and SplashScreen.png can be removed from the project. They are not used in WinUI.

Add an Icon.ico and set it on the Window

A WinUI3 should have an Icon file otherwise the app will get a blue background color in the TaskBar. It took me hours to find a solution for it. Thanks to many on the Discord group.

In the Assets/Tiles folder I would like to have an Icon.ico file with the Build Action set to Content. In the 'App.xaml.cs' file you need to call SetIcon().

For this demo I converted a Smiley.png into an Icon file using the `Simple Icon File Maker' app from Joe Finney.

/// <summary>
/// Invoked when the application is launched.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    m_window = new MainWindow();

    AppWindow appWindow = GetAppWindow(m_window);
    appWindow.SetIcon("Assets/Tiles/Icon.ico");

    // This requires WinUIEx NuGet Package
    // m_window.SetIcon("Assets/Icons/Icon.ico");

    m_window.Activate();

}

private static AppWindow GetAppWindow(Window window) {
    IntPtr hWnd = WindowNative.GetWindowHandle(window);
    WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
    return AppWindow.GetFromWindowId(wndId);
}

Image

MainWindow

Add MicaBackdrop

<Window
    x:Class="App127.Views.Windows.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:App127"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:pages="using:App127.Views.Pages"
    mc:Ignorable="d">
    <Window.SystemBackdrop>
        <MicaBackdrop />
    </Window.SystemBackdrop>
    <Grid>

The ugly white background is now gone. And you have Mica.

Image

Add the new TitleBar

If you are using WinAppSDK version 1.7 (currently in preview) you could use the new TitleBar control in your Window

<?xml version="1.0" encoding="utf-8" ?>
<Window
    x:Class="App106.Views.Windows.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:App106"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:pages="using:App106.Views.Pages"
    mc:Ignorable="d">
    <Window.SystemBackdrop>
        <MicaBackdrop />
    </Window.SystemBackdrop>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <TitleBar Title="{x:Bind Title}" Background="{ThemeResource SystemAccentColor}">
            <TitleBar.IconSource>
                <ImageIconSource ImageSource="/Assets/Tiles/StoreLogo.png" />
            </TitleBar.IconSource>
        </TitleBar>

The Title of the TitleBar is databound to the Title property of the window. The IconSource is set to the StoreLogo.png.

You also have to set the ExtendsContentIntoTitleBar and the Title, so I changed the constructor of the MainWindow into this. Using the Package.DisplayName is better than using some hard coded string.

public sealed partial class MainWindow : Window {
    public MainWindow() {
        this.InitializeComponent();

        Title = global::Windows.ApplicationModel.Package.Current.DisplayName;
        ExtendsContentIntoTitleBar = true;
    }
}

Add a Minimum size

Add a solution to the MainWindow to set the minimum size. Nobody wants this.

Image

Replace the 'Click Me' Button for a Frame and navigate to a MainPage

I think the currently used 'Click Me' button is quite useless. I think you should not have any XAML controls in a Window. Windows are limited. They cannot have Resources. In UWP apps we are used to write XAML in Pages, by default a MainPage.xaml. That is what we should do in WinUI too. We can also use the BackButton logic of the TitleBar to make that easier too.

<?xml version="1.0" encoding="utf-8" ?>
<Window
    x:Class="App106.Views.Windows.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:App106"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:pages="using:App106.Views.Pages"
    mc:Ignorable="d">
    <Window.SystemBackdrop>
        <MicaBackdrop />
    </Window.SystemBackdrop>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <TitleBar
            Title="{x:Bind Title}"
            BackRequested="TitleBar_BackRequested"
            Background="{ThemeResource SystemAccentColor}"
            IsBackButtonEnabled="True"
            IsBackButtonVisible="{x:Bind RootFrame.CanGoBack, Mode=OneWay}">
            <TitleBar.IconSource>
                <ImageIconSource ImageSource="/Assets/Tiles/StoreLogo.png" />
            </TitleBar.IconSource>
        </TitleBar>
        <Frame x:Name="RootFrame" Grid.Row="1">
            <Frame.ContentTransitions>
                <TransitionCollection>
                    <EntranceThemeTransition />
                </TransitionCollection>
            </Frame.ContentTransitions>
        </Frame>
    </Grid>
</Window>

In the constructor of the MainWindow you can navigate to a MainPage and also have the BackRequested handler.

public sealed partial class MainWindow : Window {
    public MainWindow() {
        this.InitializeComponent();

        Title = global::Windows.ApplicationModel.Package.Current.DisplayName;
        ExtendsContentIntoTitleBar = true;

        RootFrame.Navigate(typeof(MainPage));
    }

    private void TitleBar_BackRequested(TitleBar sender, object args) {
        if (RootFrame.CanGoBack) {
            RootFrame.GoBack();
        }
    }
}

This results in a Back button in the TitleBar if back navigation is possible.

Image

Introduce a MainPage with a Counter

We need a MainPage and it needs something more than only a Click Me button. In Blazor and Maui there is a Counter page. Maybe we should implement that too.

Folders

Add a GlobalUsings.cs

We don't have ImplicitUsings for WinUI apps like ASP.NET, WPF or Windows Forms. Let's create a GlobalUsings.cs file to mimic this behavior.

global using Microsoft.UI.Xaml;
global using Microsoft.UI.Xaml.Controls;
global using Microsoft.UI.Xaml.Controls.Primitives;

global using Windows.System;

Introduce a Views folder

All view related items (Windows, Pages, Resources, Controls, Dialogs) should be placed in a Views folder. Preferably with subfolders for each type.

Image

Default Styles.xaml Resource Dictionary

The project could have a Styles.xaml resource dictionary which is merged from the App.xaml file. Having a separate file for it learns unexperienced developers to use styling and the use of Resource Dictionaries.

Image

Default Themes.xaml Resource Dictionary

Add a Themes.xaml resource dictionary and reference it from the App.xaml. If new developers know that this exists, they will start using it (hopefully).

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App106.Views.Resources">
    <ResourceDictionary.ThemeDictionaries>
        <ResourceDictionary x:Key="Default">
            <!--  Dark Resources  -->
        </ResourceDictionary>
        <ResourceDictionary x:Key="Light">
            <!--  Dark Resources  -->
        </ResourceDictionary>
        <ResourceDictionary x:Key="HighContrast">
            <!--  High Contrast Resources  -->
        </ResourceDictionary>
    </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

Important Notes

I'm quite sure that there are many other improvements to be made. Is my priority ok? Please react on this proposal to get them all discussed.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions