microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.3k stars 675 forks source link

Proposal: WinUI 3 - File New Project Template should create a `MainPage` and not just a MainWindow #5515

Open michael-hawker opened 3 years ago

michael-hawker commented 3 years ago

Originally posted by @michael-hawker in https://github.com/microsoft/microsoft-ui-xaml/issues/4966#issuecomment-882958799

Yeah, I too keep getting tripped up that Window isn't a DependencyObject... it's a bit weird.

If the expectation that Window is supposed to just be the host like the implicit Frame created in App.xaml.cs for UWP apps, maybe the File -> New template for WinUI 3 should separate out the MainWindow as also having a MainPage class hosted by it already setup?

This would help lead developers to the proper constructs when building their app and set them up for success vs. having everyone start dumping UI in MainWindow and then getting frustrated.

I mean I really like how the MainWindow is more exposed compared to all the extra logic on Startup that was done in the UWP space, but it's super confusing and bare-bones template when trying to start building an app from afterwards without creating a new Page first.

I keep seeing a few issues filed because of this (and have been tripped up myself) by the fact that the default project template for WinUI 3 creates a bare Window class.

This doesn't jive as well with many UI APIs as it's not a DependencyObject/FrameworkElement. It's really just the application 'shell', like the implicit Frame that UWP apps used to create back in App.xaml.cs.

I love that this Window is now exposed and more easily customizable via XAML, but feel like it should still host a Frame which then points to a MainPage object based on Page where a developer is then led to start creating their application's UI.

Otherwise, developers just start building UI within the Window itself and get tripped up when something needs to navigate the visual tree or try to create a DependencyProperty off of it (see #4966 for instance).

crramirez commented 3 years ago

Hello @michael-hawker,

I agree. Do you have a sample application where I can copy from. Since I share code between UWP WinUI 2 & Win32 WinUI 3, it would help me a lot if I can share the MainPage as well. I saw that the WinUI 3 Controls Gallery uses this approach, but this code is quite complex.

Thanks, Carlos

michael-hawker commented 3 years ago

@crramirez I unfortunately do not have anything setup. Most of my WinUI 3 tests have just been dropping in our Toolkit controls to check that they're working.

At a minimum though you can basically replicate what the App.xaml.cs file in UWP does for you like this:

<!-- MainWindow.xaml -->
<Window ...>
  <Frame x:Name="ApplicationFrame"/>
</Window>
// MainWindow.xaml.cs
public MainWindow()
{
    this.InitializeComponent();
    ApplicationFrame.Navigate(typeof(MainPage));
}

I think that should work, just copy over your MainPage class and tweak its namespaces and then you should see it as your starting page, just like in an UWP app.

(Btw, love your github stat blog on your readme, is there a site to help generate that? Is it 'live' or static that you have to re-generate?)

crramirez commented 3 years ago

Ok, I will begin with that. I agree with you that this could help everyone to migrate a UWP app to WinUI 3 easier.

I copied the stats from another user 😏 . This is the code:

![Carlos Ramirez's GitHub Stats](https://github-readme-stats.vercel.app/api?username=crramirez&show_icons=true&count_private=true)

StephenLPeters commented 3 years ago

@evelynwu-msft FYI

JaiganeshKumaran commented 3 years ago

Frame isn't needed by default. If the user wants back and forward navigation, they can add it manually. Today the UWP templates add a root frame but I don't like that and usually, I just make MainPage a user control and set it as the content.

michael-hawker commented 3 years ago

Yeah, I think in the default case developers may want to know how to handle page navigation. It's easier for a dev to rip the frame out than realize that it's missing.

That's also why #5513 is important to point devs to the right docs for getting started or be able to find tools like Windows Template Studio to be able to make it easier to configure their app design/setup.

michael-hawker commented 1 year ago

FYI @bpulliam since #4966 got pinged again, this would be a fairly straight-forward mitigation to just update the starting template. Lead folks down a happier path by default.

michael-hawker commented 1 year ago

FYI similar to binding this also prevents a VisualStateManager (VSM) from working properly, see a discussion we had here: https://github.com/CommunityToolkit/WindowsCommunityToolkit/discussions/4848

michael-hawker commented 1 year ago

If anything, the template could just create a MainPage and reference it in the Window XAML:

<Window x:Class="ProjectTemplate.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:ProjectTemplate"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">

    <!--  Window isn't a FrameworkElement for dependency property or resources...  -->
    <local:MainPage />
</Window>

This is what I did in my template (though I'm also sharing the MainPage with the UWP head in the case anyway): https://github.com/michael-hawker/WinUI2Plus3Template/blob/main/ProjectTemplate.WinAppSDK/MainWindow.xaml

Though in the onboarding/getting started docs there should still be information here about how to setup and use a Frame model (if needed) like what is setup by default in a UWP app or alternatively hosting a NavigationView with a Frame inside it. Though it definitely needs to be called out somewhere that Window isn't mean to be used with XAML markup constructs, see folks running into this pitfall, mostly with binding, all the time.