简体   繁体   English

C++/WinRT WinUI3:如何在关闭 MainWindow 之前显示 ContentDialog?

[英]C++/WinRT WinUI3: How to show a ContentDialog before I close the MainWindow?

I'm trying to show a ContentDialog to make sure the user confirm close when they choose the close button of window. But in WinUI3, I cannot find CloseRequested Event.我试图显示一个 ContentDialog 以确保用户在选择 window 的关闭按钮时确认关闭。但是在 WinUI3 中,我找不到 CloseRequested 事件。

I trid to use AppWindow and Hwnd Interop and AppWindow.Closing , but it didn't work.我尝试使用AppWindow 和 Hwnd Interop以及AppWindow.Closing ,但没有用。 After I click the close button nothing happend.单击关闭按钮后,什么也没有发生。

I'm using Mica Window, I believe the question must be in here.我用的是Mica Window,相信问题一定出在这里。

m_closedRevoker = this->Closed(winrt::auto_revoke, [&](IInspectable const&, WindowEventArgs const& e)
    {
        if (!_closing)
        {
            _closing = true;
            e.Handled(true);
            if (have_saved)
            {
                DispatcherQueue().TryEnqueue([&](auto&& ...)
                    {
                        if (nullptr != m_backdropController)
                        {
                            m_backdropController.Close();
                            m_backdropController = nullptr;
                        }
                if (nullptr != m_dispatcherQueueController)
                {
                    m_dispatcherQueueController.ShutdownQueueAsync();
                    m_dispatcherQueueController = nullptr;
                }
                Close();
                    });
            }
            else
            {
                winrt::Microsoft::UI::Xaml::Controls::ContentDialog dialog;
                dialog.XamlRoot(Content().XamlRoot());
                dialog.Title(winrt::box_value(L"Save ?"));
                dialog.PrimaryButtonText(L"Yes");
                dialog.SecondaryButtonText(L"No");
                dialog.CloseButtonText(L"Cancel");
                dialog.DefaultButton(winrt::Microsoft::UI::Xaml::Controls::ContentDialogButton::Primary);
                dialog.PrimaryButtonClick([&](auto&& ...)
                    {
                        if (save_data(winrt::Lexical_Frequency::implementation::amount))
                        {
                            DispatcherQueue().TryEnqueue([&](auto&& ...)
                                {
                                    if (nullptr != m_backdropController)
                                    {
                                        m_backdropController.Close();
                                        m_backdropController = nullptr;
                                    }
                            if (nullptr != m_dispatcherQueueController)
                            {
                                m_dispatcherQueueController.ShutdownQueueAsync();
                                m_dispatcherQueueController = nullptr;
                            }
                            Close();
                                });
                        }
                    });
                dialog.SecondaryButtonClick([&](auto&& ...)
                    {
                        DispatcherQueue().TryEnqueue([&](auto&& ...)
                            {
                                if (nullptr != m_backdropController)
                                {
                                    m_backdropController.Close();
                                    m_backdropController = nullptr;
                                }
                                if (nullptr != m_dispatcherQueueController)
                                {                                       m_dispatcherQueueController.ShutdownQueueAsync();
                                    m_dispatcherQueueController = nullptr;
                                }
                                Close();
                            });
                    });

                dialog.ShowAsync().Completed([&](auto&& ...)
                    {
                        _closing = false;
                    });
            }
        }
    });

Here is a solution based on the Window.Closed event which has an Handled property we can use.:这是一个基于Window.Closed 事件的解决方案,它具有我们可以使用的Handled 属性

In MainWindow.cpp:在 MainWindow.cpp 中:

namespace winrt::WinUIApp1CPP::implementation
{
    MainWindow::MainWindow()
    {
        InitializeComponent();

        _closing = false;
        Closed([&](IInspectable const&, WindowEventArgs const& e)
            {
                if (!_closing)
                {
                    _closing = true;
                    e.Handled(true);

                    ContentDialog dialog;
                    dialog.XamlRoot(Content().XamlRoot());
                    dialog.Title(box_value(L"Do you really want to close the app?"));
                    dialog.PrimaryButtonText(L"Yes, close");
                    dialog.CloseButtonText(L"No, cancel");
                    dialog.DefaultButton(ContentDialogButton::Close);
                    dialog.PrimaryButtonClick([&](auto&& ...)
                        {
                            DispatcherQueue().TryEnqueue([&](auto&& ...)
                                {
                                    Close();
                                });
                        });

                    dialog.ShowAsync().Completed([&](auto&& ...)
                        {
                            _closing = false;
                        });
                }
            });
    }
}

With MainWindow.h:使用 MainWindow.h:

namespace winrt::WinUIApp1CPP::implementation
{
    struct MainWindow : MainWindowT<MainWindow>
    {
        MainWindow();
        ...
        bool _closing;
        ...
   };
}

And for what it's worth, the equivalent in C#:对于它的价值,相当于 C#:

public MainWindow()
{
    InitializeComponent();

    var closing = false;
    Closed += async (s, e) =>
    {
        if (!closing)
        {
            closing = true;
            e.Handled = true;

            var dialog = new ContentDialog();
            dialog.XamlRoot = Content.XamlRoot;
            dialog.Title = "Do you really want to close the app?";
            dialog.PrimaryButtonText = "Yes, close";
            dialog.CloseButtonText = "No, cancel";
            dialog.DefaultButton = ContentDialogButton.Close;
            dialog.PrimaryButtonClick += (s, e) => DispatcherQueue.TryEnqueue(Close);
            var result = await dialog.ShowAsync();
            closing = false;
        }
    };
}

Note: the usage of DispatcherQueue.TryEnqueue should not be necessary but without it, the Close() call currently causes a crash in WinUI3...注意: DispatcherQueue.TryEnqueue的使用不是必需的,但如果没有它,Close() 调用当前会导致 WinUI3 崩溃...

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

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