0

I have a button in my Xaml code like this:

<Button x:Name="PickFolderButton" Click="PickFolderButton_Click"/>

and the code behind is this:

    private async void PickFolderButton_Click(object sender, RoutedEventArgs e)
    {
        BackupDestinationText.Text = "";

        FolderPicker openPicker = new FolderPicker();

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

        WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);

        openPicker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
        openPicker.FileTypeFilter.Add("*");

        StorageFolder folder = await openPicker.PickSingleFolderAsync();
        if (folder != null)
        {
            StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedFolderToken", folder);
            BackupDestinationText.Text = folder.Path;
        }
        else
        {
            BackupDestinationText.Text = "Operation cancelled";
        }
    }

Yet, if I run this code (press the button), then I get a general break, it points to the file App.g.i.cs, line 68, global::System.Diagnostics.Debugger.Break();, which is not helpful at all (see image for an inline image).

After @Simon Mourier's suggestion, I tried using the debugger to get more info on the error, with it, I got this error in the DispatcherQueueSynchronizationContext.cs file, which is read only:

System.InvalidCastException
  HResult=0x80004002
  Message=Specified cast is not valid.
  Source=WinRT.Runtime
  StackTrace:
   at WinRT.ComWrappersSupport.CreateCCWForObjectForABI(Object obj, Guid iid) in WinRT\ComWrappersSupport.cs:line 888
   at WinRT.MarshalInspectable`1.CreateMarshaler2(T o, Guid iid, Boolean unwrapObject) in WinRT\MarshalInspectable.cs:line 53
   at WinRT.Interop.IWindowNativeMethods.get_WindowHandle(Object _obj) in WinRT.Interop\IWindowNativeMethods.cs:line 11
   at WinRT.Interop.WindowNative.GetWindowHandle(Object target) in WinRT.Interop\WindowNative.cs:line 9
   at BackupTool.Views.NewProfilePage.<PickFolderButton_Click>d__10.MoveNext() in C:\Users\user\source\repos-private\BackupTool\Views\NewProfilePage.xaml.cs:line 126
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state) in System.Threading.Tasks\Task.cs:line 1851
   at Microsoft.UI.Dispatching.DispatcherQueueSynchronizationContext.<>c__DisplayClass2_0.<Post>b__0() in Microsoft.UI.Dispatching\DispatcherQueueSynchronizationContext.cs:line 29

  This exception was originally thrown at this call stack:
    WinRT.ComWrappersSupport.CreateCCWForObjectForABI(object, System.Guid) in ComWrappersSupport.cs
    WinRT.MarshalInspectable<T>.CreateMarshaler2(T, System.Guid, bool) in MarshalInspectable.cs
    WinRT.Interop.IWindowNativeMethods.get_WindowHandle(object) in IWindowNativeMethods.cs
    WinRT.Interop.WindowNative.GetWindowHandle(object) in WindowNative.cs
    BackupTool.Views.NewProfilePage.PickFolderButton_Click(object, Microsoft.UI.Xaml.RoutedEventArgs) in NewProfilePage.xaml.cs
    System.Threading.Tasks.Task.ThrowAsync.AnonymousMethod__128_0(object) in Task.cs
    Microsoft.UI.Dispatching.DispatcherQueueSynchronizationContext.Post.AnonymousMethod__0() in DispatcherQueueSynchronizationContext.cs```


After some trial and error, it seems that following line in by button code is the culprit:
```cs
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);

It seems like the same issue as this post, on which the working answer was this from @mm8. It goes as follows:

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; 

I've tried adding both proposed solutions to my App.xaml.cs file, of which only the first one did not get an error (second one said: CS0103 The name 'm_window' does not exist in the current context), yet it didn't work (probably because m_Window was never in App.xaml.cs to begin with).

How can I use var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);?

lajawi
  • 101
  • 3
  • It's not super intuitive but when you get to `global::System.Diagnostics.Debugger.Break();` you do have an exception that you can look at using the debugger. Also make sure `this` is of `Window` type. – Simon Mourier Aug 12 '23 at 15:56
  • @SimonMourier I've updated the question, with a more detailed error I got while using the debugger. I cannot cast `this` to a `Window` type like this (`(Window)this`). How else would I go about making it a type `Window`? – lajawi Aug 12 '23 at 16:11
  • What's the type you're calling GetWindowHandle from (ie: what's the type of `this`)? – Simon Mourier Aug 12 '23 at 18:00
  • @AndrewKeepCoding, generally, yes, it does. A few things though: 1) I had to name the variable `MainWindow` added in `App.xaml.cs` something else, as there was one already, which, if replaced, causes compile error [`CS0117`](https://learn.microsoft.com/en-us/dotnet/csharp/misc/cs0117?f1url=%3FappId%3Droslyn%26k%3Dk(CS0117)) (the line which I removed was `public static WindowEx MainWindow { get; } = new MainWindow();`), 2) clicking the corresponding button opens an empty, extra window. If I then close this window and press the button again, the program breaks, if it stays open, it keeps working – lajawi Aug 13 '23 at 09:43
  • About 1: If your app is using `WinUIEx`, you don't need to add another `MainWindow` property in App.xaml.cs. Keep the line `public static WindowEx MainWindow { get; } = new MainWindow();` and `WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);` should work. – Andrew KeepCoding Aug 13 '23 at 21:35
  • About 2: Are you saying that `StorageFolder folder = await openPicker.PickSingleFolderAsync();` opens an empty window? If that's the case, can you post another question with minimal reproducible code? – Andrew KeepCoding Aug 13 '23 at 21:38
  • It seems your solution to problem 1, has solved problem 2 as well. Only thing is, that the button which opens the folderpicker is in a second window, so if the folderpicker opens, it focusses on the first window. Not a big deal, but one I'd nonetheless like to get rid off. – lajawi Aug 14 '23 at 07:52
  • @AndrewKeepCoding – lajawi Aug 15 '23 at 13:19

0 Answers0