How to retrieve the window handle of the current WinUI 3 MainWindow from a page in a frame in a NavigationView control on the MainWindow
Asked Answered
R

2

8

I am creating my first WinUI 3 desktop application. I have a NavigationView on my MainWindow. I have 9 different pages that I navigate to via the frame in the NavigationView. One of the pages is for printing reports. I need to get the FileSavePicker to work from the 'reportPage'. I have implemented the below, directly following the examples from the learn.microsoft.com. (I also added the same FileSavePicker code segment below to a small dummy winui-3 sand-box test app, but instead I put the code on the MainWindow's code-behind and it worked perfectly.) I need to get the FileSavePicker to work from a page instead of a MainWindow. Thank you all for your help so far.

I get this debug error:

enter image description here

I know the problem has to do with getting the MainWindow's HWND.

// Retrieve the window handle (HWND) of the current WinUI 3 window.
   var window = (MainWindow)Application.Current.MainWindow; (I tried this, but it did not work)

I get this error from the above line: enter image description here

(I tried this, but it did not work)

   var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window); 

I get this error from the line above:

enter image description here

I don't know the correct syntax.

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Provider;
    
namespace MetricReporting.Pages
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class pageReports : Page
    {
        public pageReports()
        {
            this.InitializeComponent();
        }

        private void ButtonBoltReport_Click(object sender, RoutedEventArgs e)
        {
            DisplayBOLTSaveDialog();
        }

        private async void DisplayBOLTSaveDialog()
        {

            FileSavePicker savePicker = new FileSavePicker();

            // Retrieve the window handle (HWND) of the current WinUI 3 window.
            var window = (MainWindow)Application.Current.MainWindow;
            var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);

            // Initialize the folder picker with the window handle (HWND).
            WinRT.Interop.InitializeWithWindow.Initialize(savePicker, hWnd);

            savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
            // Dropdown of file types the user can save the file as
            savePicker.FileTypeChoices.Add("Plain Text", new List<string>() { ".txt" });
            // Default file name if the user does not type one in or select a file to replace
            savePicker.SuggestedFileName = "New Document";

            StorageFile file = await savePicker.PickSaveFileAsync();
            if (file != null)
            {
                // Prevent updates to the remote version of the file until we finish making changes and call CompleteUpdatesAsync.
                CachedFileManager.DeferUpdates(file);
                // write to file
                await FileIO.WriteTextAsync(file, file.Name);
                // Let Windows know that we're finished changing the file so the other app can update the remote version of the file.
                // Completing updates may require Windows to ask for user input.
                FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);
                if (status == FileUpdateStatus.Complete)
                {
                    ReportStatus.Text = "File " + file.Name + " was saved.";
                }
                else
                {
                    ReportStatus.Text = "File " + file.Name + " couldn't be saved.";
                }
            }
            else
            {
                ReportStatus.Text = "Operation cancelled.";
            }
            
        }
    }
}
Recalcitrant answered 11/3, 2022 at 0:13 Comment(3)
"It did not work" is not a useful problem description without telling us why it didn't work - it has the opposite effect: it makes us less inclined to help you with your problem simply from driving up my blood pressure to the point where I die of a heart attack and collapse on my keyboa3wqef32r[23t 223r311Bramwell
My apologies. I am editing my post to include more details concerning my attempt to get this to work. Thanks.Recalcitrant
@Recalcitrant Please don't post pictures of code or errors as we can't copy them.Sammysamoan
E
19

Change the modifier for the m_window field in App.xaml.cs:

internal Window m_window;

...or better yet expose it through a property:

public Window Window => m_window;

Then you can access the window from the page like this:

var window = (Application.Current as App)?.m_window as MainWindow; 

or

var window = (Application.Current as App)?.Window as MainWindow; 
Etheridge answered 11/3, 2022 at 15:24 Comment(1)
Thank you mm8! That worked! I did already have this in my App.xaml.cs 'internal window m_window;' From a previous solution you gave me. I added this line in my page: var window = (Application.Current as App)?.m_window as MainWindow;, and now the FileSavePicker appears! You are the best!Recalcitrant
B
1

Update (2024 April)

I discovered another way to do it, which is described in the WinUI 3 Gallery app published by Microsoft. It is located in their examples under System > FilePicker.

It reads:

In App.xaml.cs, you can make MainWindow accessible by making it static.

Here's the code snippet they provided, which worked for me.

public partial class App : Application
{
    public static MainWindow MainWindow = new();

    public App()
    {
        this.InitializeComponent();
    }

    protected override void OnLaunched(LaunchActivatedEventArgs args)
    {
        MainWindow.Activate();
    }
}

Then in my other files, I can simply write App.MainWindow to reference the window.

Bowshot answered 23/4 at 18:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.