winui-3argumentexceptioncontentdialog

How to create a content dialog in App.xaml.cs in WinUI3?


I'm making a small app with WinUI 3. The app require to connect to the Internet while loading. Then it will download some necessary resources. I can't put the network check under any one window, because all windows need the resources which have downloaded, otherwise they won't start properly. So I added a network check in the Onlaunch method in App.xaml.cs. There are the codes.

if (SystemEnvironmentHelper.IsConnectInternet() == false)
{
    //No wifi connection
    ContentDialog noWifiDialog = new ContentDialog()
    {
        Title = "No wifi connection",
        Content = "Check connection and try again.",
        CloseButtonText = "Ok"
    };

    await noWifiDialog.ShowAsync();
}

And the IsConnectInternetmethod is defined as follows.(Actually it works well)

[DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(ref int Description, int ReservedValue);
public static bool IsConnectInternet()
{
    int Description = 0;
    return InternetGetConnectedState(ref Description, 0);
}

But when I run this app, it throw an exception System.ArgumentException. I know I should add XamlRoot, but no form is declared in App.xaml.cs, and XamlRoot does not exist. I don't know how to solve this problem because there are only a few documents and they didn't mention this problem.

Also, I'm using an unpackaged app, does Content Dialog work with unpackaged apps?

Any help are appreciated.


Solution

    1. You should create and display a window as soon as possible after the app has been started regardless of whether you intend to display a ContentDialog. It doesn't have to be your "main" window but you should display something to confirm that your app is actually running.

    2. You cannot show a ContentDialog until there are some content displayed on the screen.

    You could for example create a temporary window that shows a ProgressRing while you check the connection:

    <Window
        x:Class="App1.TempWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid>
            <ProgressRing IsIndeterminate="True" />
        </Grid>
    </Window>
    

    Once the temporary window has been shown, you can then check the connection and display the dialog:

    public partial class App : Application
    {
        public App()
        {
            this.InitializeComponent();
        }
    
        protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
        {
            // 1. Show "temp" window
            m_window = new TempWindow();
            (m_window.Content as FrameworkElement).Loaded += OnLoaded;
            m_window.Activate();
    
        }
    
        private async void OnLoaded(object sender, RoutedEventArgs e)
        {
            // 2. Check connection and show dialog
            (m_window.Content as FrameworkElement).Loaded -= OnLoaded;
    
            //if (SystemEnvironmentHelper.IsConnectInternet() == false)
            {
                //No wifi connection
                ContentDialog noWifiDialog = new ContentDialog()
                {
                    Title = "No wifi connection",
                    Content = "Check connection and try again.",
                    CloseButtonText = "Ok",
                    XamlRoot = m_window.Content.XamlRoot
                };
    
                await noWifiDialog.ShowAsync();
            }
    
            // 3. Show main window
            var mainWindow = new MainWindow();
            mainWindow.Activate();
    
            // 4. Close "temp" window
            m_window.Close();
            m_window = mainWindow;
        }
    
        private Window m_window;
    }