2

I have a WinUi3 app written in C++.

I want to show a "MessageBox" before displaying the main window of the application (only sometimes, and based on some switch received in command line).

I tried to put this code in App::OnLaunched() but it throws an Exception:

Exception thrown at 0x00007FFD661100AC (KernelBase.dll) in App1.exe: WinRT originate error - 0x80070057 : 'This element does not have a XamlRoot. Either set the XamlRoot property or add the element to a tree.'.

The code is:

window = make<MainWindow>();
window.Activate();

winrt::Microsoft::UI::Xaml::Controls::ContentDialog dialog;
dialog.Title(box_value(L"Modern Dialog"));
dialog.Content(box_value(L"WinUI 3 ContentDialog"));
dialog.CloseButtonText(L"OK");
dialog.XamlRoot(window.Content().XamlRoot());

dialog.ShowAsync();

How to make the ContentDialog display?

1
  • My purpose is to show only the ContentDialog and MainWindow should never be visible. But I have problems obtaining a valid XamlRoot. Anyways I will study Task Dialog! Commented Jun 11 at 20:35

3 Answers 3

3

I'm not familiar with WinUI, but it sounds like you are trying to use the main window's XamlRoot before it is actually ready.

Per comments on Show ContentDialog without setting XamlRoot? in Microsoft's WinUI GitHub repo:

I don't work in this area of the platform, but as I suggested in #2848. I don't think you want to be using ContentDialog here, you should just open a window. ContentDialog's today are meant to be displayed in an existing window, they're not a top-level window concept themselves.

...

ContentDialog requires a xaml root in order to draw to the screen. If your app doesn't have any other content drawing to the screen then ContentDialog wont work for your scenario. I'd suggest making a window to contain the UI you intend to show.

Since you don't want to show your MainWindow, then you can't use its XamlRoot to show the ContentDialog. You will have to create a separate popup window whose sole job is to host the ContentDialog.

Otherwise, as a workaround, you might consider using the Win32 Task Dialog API, which can be displayed without having to specify an owner/parent window, eg:

TaskDialog(nullptr, nullptr, L"Modern Dialog", nullptr, L"WinAPI TaskDialog", TDCBF_OK_BUTTON, nullptr, nullptr);
Sign up to request clarification or add additional context in comments.

3 Comments

Related: #6559.
Thanks for info! 1) I tried TaskDialog and it works but it looks horrible because its width is too short and it breaks the sentence at wrong point. 2) Eventually I will make a dedicated window for this but I wanted to use something built-in in order to avoid computing windows size and buttons size! I will display this window with different texts but the layout will be the same!
TaskDialogIndirect() allows you to control the width of the dialog
1

Let me give you another workaround that doesn't require the XamlRoot. This is C# but I guess you can apply to C++.

First, we create a custom window for the dialog.

DialogWindow.xaml

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

    <StackPanel Orientation="Horizontal">
        <Button Content="OK" Click="OKButton_Click" />
        <Button Content="Cancel" Click="CancelButton_Click"/>
    </StackPanel>

</Window>

DialogWindow.xaml.cs

public sealed partial class DialogWindow : Window
{
    public DialogWindow(int width, int height)
    {
        InitializeComponent();

        Width = width;
        Height = height;

        this.AppWindow.Resize(new Windows.Graphics.SizeInt32(Width, Height));

        if (this.AppWindow.Presenter is OverlappedPresenter overlappedPresenter)
        {
            overlappedPresenter.IsResizable = false;
            overlappedPresenter.IsMaximizable = false;
            overlappedPresenter.IsMinimizable = false;
            overlappedPresenter.IsAlwaysOnTop = true;
        }
    }

    public enum DialogResult
    {
        OK,
        Cancel
    }

    public int Width { get; }

    public int Height { get; }

    public DialogResult Result { get; private set; } = DialogResult.Cancel;

    private void OKButton_Click(object sender, RoutedEventArgs e)
    {
        Result = DialogResult.OK;
        this.Close();
    }

    private void CancelButton_Click(object sender, RoutedEventArgs e)
    {
        Result = DialogResult.Cancel;
        this.Close();
    }
}

Then we use it in App.xaml.cs before activating the MainWindow:

public partial class App : Application
{
    private DialogWindow? _startUpWindow;
    private Window? _window;

    public App()
    {
        InitializeComponent();
    }

    protected override void OnLaunched(LaunchActivatedEventArgs args)
    {
        _startUpWindow = new DialogWindow(500, 300);
        _startUpWindow.Closed += (s, e) =>
        {
            var result = _startUpWindow?.Result ?? DialogWindow.DialogResult.Cancel;
            _startUpWindow = null;

            if (result == DialogWindow.DialogResult.OK)
            {
                _window = new MainWindow();
                _window.Activate();
                return;
            }
        };

        _startUpWindow.Activate();
    }
}

Comments

-1

If you realy need just MessageBox features in context where moden dialogs are not available, you can use old good MessageBox directly from Windows.h

// At top of file
#include <Windows.h>

// For example, in App::OnLaunched
MessageBox(0, L"Text", L"Caption", MB_OK);

2 Comments

Good old MessageBox looks like a really old MessageBox and I do no want that!
Then you need to properly setup XamlRoot as other anwer suggest.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.