-
Notifications
You must be signed in to change notification settings - Fork 802
Description
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 | ||
| 5 | MainWindow - Add the new TitleBar | Must |
| 6 | MainWindow - Add a Minimum size | Must |
| 7 | ||
| 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.
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);
}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.
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.
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.
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.
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.
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.






