简体   繁体   English

WinUI3:启动时从 main window 显示对话框?

[英]WinUI3: display dialog at startup from main window?

I'm getting started with WinUI3.我开始使用 WinUI3。 Having no previous experience with UWP or WPF or even much C#, it's tough going.之前没有使用 UWP 或 WPF 甚至很多 C# 的经验,这很难进行。

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.假设我们从一个由 Visual Studio 生成的简单应用开始。 We have a MainWindow class defined in MainWindow.xaml.cs and its associated XAML (MainWindow.xaml).我们在 MainWindow.xaml.cs 及其关联的 XAML (MainWindow.xaml) 中定义了MainWindow class。 I believe the class is called a code-behind class.我相信 class 被称为代码隐藏 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?看起来好像ContentDialog是通往 go 的路。但是如何显示它呢? As I understand it, I'm going to need to set the XamlRoot, so naively I tried this:据我了解,我需要设置 XamlRoot,所以我天真地尝试了这个:

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:调用时,主窗口的 XAML 根是 null 并试图显示对话框抛出异常:

在此处输入图像描述

How do I detect when it's ok to use the main window's XAML root?如何检测何时可以使用主窗口的 XAML root? This issue seems to hint at an OnLoaded event, but I can't find anything about OnLoaded events in WinUI. 这个问题似乎暗示了一个OnLoaded事件,但我在 WinUI 中找不到任何关于 OnLoaded 事件的信息。 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, ie我能让它工作的唯一方法是连接到窗口的按钮并响应它的 Loaded 事件,即

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.我什至不知道它是否保证 XamlRoot 将是非空的,只是因为一个按钮已加载。 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?那么当我只有主要的 window 时,我应该如何实现在屏幕上放置对话框的简单任务呢?

All help very gratefully received.非常感谢收到所有帮助。 Please try to make any answers as newbie-friendly as possible.请尽量让任何答案尽可能对新手友好。

Unfortunately, the MainWindow has no Loaded events.不幸的是, MainWindow没有Loaded事件。 What you can do is to work with a Page instead.您可以做的是改为使用Page So basically use the MainWindow as a "Window" and use Pages for your contents.所以基本上将MainWindow用作“窗口”并使用Pages作为您的内容。

MainPage.xaml.cs MainPage.xaml.cs

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        this.Loaded += MainPage_Loaded;
    }

    private async void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        var dlg = new ContentDialog();
        dlg.XamlRoot = this.XamlRoot;
        dlg.Content = "Hello World";
        await dlg.ShowAsync();
    }
}

MainWindow.xaml主窗口.xaml

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

    <local:MainPage />

</Window>

A WinUI Window is just an abstraction of each of the low-level window implementations used by supported (UWP and desktop) app models. WinUI Window只是受支持的(UWP 和桌面)应用程序模型使用的每个低级 window 实现的抽象。

The "trick" is to handle the Loaded event of the window's root element. “技巧”是处理窗口根元素的Loaded事件。 The default template includes a Grid root element.默认模板包括一个Grid根元素。 A "generic" solution could be implemented something like this: “通用”解决方案可以这样实现:

public MainWindow()
{
    this.InitializeComponent();
    var root = this.Content as FrameworkElement;
    if (root != null)
        root.Loaded += async (s, e) => await DisplayDialog();

}

private async Task DisplayDialog()
{
    var dlg = new ContentDialog();
    dlg.XamlRoot = this.Content.XamlRoot;
    dlg.Content = "Hello World";
    await dlg.ShowAsync();
}

Also tote that an async method, with the exception of event handlers, should return a Task or a Task<T> and be awaited by the caller.另请注意, async方法(事件处理程序除外)应返回TaskTask<T>并由调用者awaited

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM