modal-dialogmauiwinui-3maui-blazor

How do I make a modal multi-window in .NET Maui?


I'm opening a second Window in .NET Maui via Application.Current.OpenWindow(), and was wondering if there was a solution to make this second Window "modal" (e.g. the second window must be closed before you can interact with the parent window again). I've been doing a bit of research online and ran into a few deadends. I'm still learning in the process of learning about Maui, Blazor, and XAML, so I appreciate your understanding if I jumble some of the terms.

In my Razor component (DialogueTest.razor), I made this function to launch a second window.

public void ModalWindowLaunch()
   {
       Window secondWindow = new Window()
           {
               Page = new WindowPage(),
           };
       Application.Current.OpenWindow(secondWindow);
   }

This function uses a class, WindowPage, I created that inherits from ContentPage

public partial class WindowPage : ContentPage

In this class, I added the following code based on this Microsoft Learn post.

var mauiWindow = this.Window.Handler.VirtualView;
var nativeWindow = this.Window.Handler.PlatformView as Microsoft.Maui.MauiWinUIWindow;
nativeWindow.Activate();
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(nativeWindow);
var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
var p = appWindow.Presenter as Microsoft.UI.Windowing.OverlappedPresenter;
p.IsModal = true;

However, I get an exception: "The window should have an owner when IsModal=true". I have been unable to find any leads on how to assign ownership to the parent window in Maui, as it seems ownership needs to be assigned at creation, but Application.Current.OpenWindow is creating the window without ownership (could be wrong on this).

I also tried await Navigation.PushModalAsync(new WindowPage()); but this does not display the parent window while the new Page object is pushed onto the modal stack (a behavior I'd like to avoid, I want both windows to be visible, with the parent being non-interactive)

Is my approach incorrect? Should I disabling / freezing the parent window via Maui instead of trying to make changes with the WinUI? Any tips or suggestions would be greatly appreciated.


Solution

  • wondering if there was a solution to make this second Window "modal" (e.g. the second window must be closed before you can interact with the parent window again).

    At first I wanted to use Popup of .NET MAUI Community Toolkit to implement, but it cannot be used in Blazor.

    However, you can use the following code to achieve it:

    Create a MAUI Blazor project and then add a Razor Component named: Modalpopuplayout.razor:

    @inherits LayoutComponentBase
    
    
    @Body
    
    
    @code {
    
    
    }
    

    For Index.razor, change to this:

    @page "/"
    @layout Modalpopuplayout
    <button @onclick="()=>{ispopup=true;}" class="btn btn-light" type="button" data-bs-dismiss="modal">Show Modal</button>
    
    
    @if (ispopup)
    {
        <div class="modal fade show" role="dialog" tabindex="-1" id="modal-1" style="display: block;    background-color: #0000005c;">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h4 class="modal-title">Modal Title</h4>
                        <button type="button" @onclick="()=>{ispopup=false;}" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <p>The content of your modal.</p>
                    </div>
                    <div class="modal-footer">
                        <button class="btn btn-light" @onclick="()=>{ispopup=false;}" type="button" data-bs-dismiss="modal">Close</button>
                        <button class="btn btn-primary" type="button">Save</button>
                    </div>
                </div>
            </div>
        </div>
    
    
    }
    
    @code {
        bool ispopup = false;
        }
    

    Run the project and here is the effect.

    In addition, You can also refer to the solution of this case: Creating a popup in Blazor using C# method.