I’m getting started with WinUI3. Having no previous experience with UWP or WPF or even much C#, it’s tough going.
Today’s question is how to display a simple dialog at startup. Consider that we start with a simple app, as generated by Visual Studio. We have a MainWindow
class defined in MainWindow.xaml.cs and its associated XAML (MainWindow.xaml). I believe the class is called a code-behind class.
So I want to do something as simple as display a dialog when the (desktop) app runs. It looks as though a ContentDialog
is the way to go. But how to display it? As I understand it, I’m going to need to set the XamlRoot, so naively I tried this:
public MainWindow()
{
this.InitializeComponent();
DisplayDialog();
}
private async void DisplayDialog()
{
var dlg = new ContentDialog();
dlg.XamlRoot = this.Content.XamlRoot; // <-- set the XAML root here, but it's null
dlg.Content = "Hello World";
await dlg.ShowAsync();
}
This doesn’t work. When called, the main window’s XAML root is null and trying to show the dialog throws an exception:
How do I detect when it’s ok to use the main window’s XAML root? This issue seems to hint at an OnLoaded
event, but I can’t find anything about OnLoaded events in WinUI. Did I miss something?
This only way I can get this to work is to hook into the window’s button and respond to its Loaded event, i.e.
public MainWindow()
{
this.InitializeComponent();
myButton.Loaded += MyButton_Loaded; // <-- hack
}
private void MyButton_Loaded(object sender, RoutedEventArgs e)
{
DisplayDialog();
}
private async void DisplayDialog()
{
var dlg = new ContentDialog();
dlg.XamlRoot = this.Content.XamlRoot; // <-- this is non-null now!
dlg.Content = "Hello World";
await dlg.ShowAsync();
}
But this feels really dirty. I don’t even know if it’s guaranteed that the XamlRoot will be non-null just because a button has loaded. And anyway, latching onto the button load seems very much like a hack. It relies on there being a button for one thing!
So how should I achieve the simple task of putting a dialog on the screen when all I have is the main window?
All help very gratefully received. Please try to make any answers as newbie-friendly as possible.
2
Answers
Unfortunately, the
MainWindow
has noLoaded
events. What you can do is to work with aPage
instead. So basically use theMainWindow
as a "Window" and usePages
for your contents.MainPage.xaml.cs
MainWindow.xaml
A WinUI
Window
is just an abstraction of each of the low-level window implementations used by supported (UWP and desktop) app models.The "trick" is to handle the
Loaded
event of the window’s root element. The default template includes aGrid
root element. A "generic" solution could be implemented something like this:Also tote that an
async
method, with the exception of event handlers, should return aTask
or aTask<T>
and beawaited
by the caller.