Closed andrewleader closed 3 years ago
Can you provide simple example how do you provide reference to window from page object ? Usually an app consists of one main window and multiple pages where main window it's just a container without any logic, everything happens in pages so we need to know how to use it from page level.
@KWodarczyk in most cases, for apps that only have one window, you can create a public static reference in App.xaml.cs to your main window
App.xaml.cs
public static Window Window => m_window;
And then from other files, call it like...
GetWindowHandle(App.Window);
@andrewleader that will work if you have all your pages in same project as App.xmal.cs but I have separated them to two separate project, so views are separate form the winui project so hat I can use views if i want to switch to UWP or WPF etc. The simplest way is just to add reference to winui project to my views project abut I don't want to add whole project just to get to the window. I also tried to use VisualTreeHelper in a Page code behind to get to the window but that does not work either.
Just in case. Add a FileTypeFilter when using the FolderPicker. It works without the FileTypeFilter on a Windows 11, but you (might?) get a COMException on Windows 10.
FolderPicker folderPicker = new();
folderPicker.FileTypeFilter.Add("*");
IntPtr hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hwnd);
StorageFolder folder = await folderPicker.PickSingleFolderAsync();
Damn, this is a leaky abstraction. It's made even worse given that generally you would invoke this from a view model which has no concept as to the window it's owned by.
Just in case. Add a FileTypeFilter when using the FolderPicker. It works without the FileTypeFilter on a Windows 11, but you (might?) get a COMException on Windows 10.
FolderPicker folderPicker = new(); folderPicker.FileTypeFilter.Add("*"); IntPtr hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hwnd); StorageFolder folder = await folderPicker.PickSingleFolderAsync();
Yes, there probably is, since the picker does not open on Windows 10. But
folderPicker.FileTypeFilter.Add("*");
does the trick.
Tried with Windows 11 and it doesn't work anymore. WASDK 1.1 preview 3, but only if I use my app as elevated, otherwise it works.
I am trying to use FileSavePicker with the required parameters, including the WindowHandle and it fails. (The commented section for FileSavePicker causes an unhandled exception without further details). If I use the FileOpenPicker with the Window Handle the dialog opens as expected.
The section of code that has been commented out relates to the FileSavePicker and although using the correct window handle it doesn't work.
I believe I have set all required values for the FileSavePicker. What am I missing?
FileOpenPicker filePicker = new();
/
FileSavePicker picker = new();
picker.SuggestedStartLocation = PickerLocationId.Downloads;
picker.FileTypeChoices.Add("Csv", new List
var hwnd = WindowNative.GetWindowHandle(App.m_window); InitializeWithWindow.Initialize(filePicker, hwnd); //InitializeWithWindow.Initialize(picker, hwnd); filePicker.FileTypeFilter.Add("*");
//StorageFile file = await picker.PickSaveFileAsync(); StorageFile file = await filePicker.PickSingleFileAsync();
Hi @rayveenemadotmacdotcom! I couldn't reproduce your problem on both Win10 and Win11. All I did was just create a WinUI3 app and use the sample button to open the FileSavePicker
and replace App.m_window
with this
which is the MainWindow
.
Maybe you should check if you are getting a valid hwnd
.
private async void myButton_Click(object sender, RoutedEventArgs e)
{
FileSavePicker picker = new();
picker.SuggestedStartLocation = PickerLocationId.Downloads;
picker.FileTypeChoices.Add("Csv", new List<string>() { ".csv" });
picker.FileTypeChoices.Add("Plain Text", new List<string>() { ".txt" });
picker.SuggestedFileName = "Activity Codes";
picker.SettingsIdentifier = "settingsIdentifier";
picker.DefaultFileExtension = ".csv";
var hwnd = WindowNative.GetWindowHandle(this); // App.m_window?
InitializeWithWindow.Initialize(picker, hwnd);
StorageFile file = await picker.PickSaveFileAsync();
myButton.Content = $"{file?.DisplayName}";
}
Andrew it works on a Windows, but when you use Pages it doesn’t. I use the navigation view. The window handle works as I can execute the FileOpenPicker, as in the example code showed. So I know from my page I can execute with a valid window handle.
Give it a try from a page from Navigation view and see if it works.
On May 12, 2022, at 10:10 PM, Andrew KeepCoding @.***> wrote:
Hi @rayveenemadotmacdotcom! I couldn't reproduce your problem on both Win10 and Win11. All I did was just create a WinUI3 app and use the sample button to open the FileSavePicker and replace App.m_window with this which is the MainWindow.
Maybe you should check if you are getting a valid hwnd.
private async void myButton_Click(object sender, RoutedEventArgs e) { FileSavePicker picker = new(); picker.SuggestedStartLocation = PickerLocationId.Downloads; picker.FileTypeChoices.Add("Csv", new List<string>() { ".csv" }); picker.FileTypeChoices.Add("Plain Text", new List<string>() { ".txt" }); picker.SuggestedFileName = "Activity Codes"; picker.SettingsIdentifier = "settingsIdentifier"; picker.DefaultFileExtension = ".csv"; var hwnd = WindowNative.GetWindowHandle(this); // App.m_window? InitializeWithWindow.Initialize(picker, hwnd); StorageFile file = await picker.PickSaveFileAsync(); myButton.Content = $"{file?.DisplayName}"; }
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.
@rayveenemadotmacdotcom I tried it on a page inside MainWindow
, a page inside a NavigationView
(created with Template Studio) on both Win10 and Win11 and works. I should've ask you this first, but, which code exactly is giving you the exception? the PickSaveFileAsync()
? Can you reproduce this with the minimum code? 🤔
So I have created a new NavigationView app using Template Studio for VS Professional 2022 and the FileSavePicker works using the GetWindowHandle. This means that my WinUI 3 app that I generated not using Template Studio must have a setting or some discrepancy causing FileSavePicker to not work in the NavigationView solution.
I will dig into my original app and see if I can find the culprit knowing that the FileSavePicker should work.
I’ll post my findings.
On May 13, 2022, at 1:19 AM, Andrew KeepCoding @.***> wrote:
@rayveenemadotmacdotcom https://github.com/rayveenemadotmacdotcom I tried it on a page inside MainWindow, a page inside a NavigationView (created with Template Studio) on both Win10 and Win11 and works. I should've ask you this first, but, which code exactly is giving you the exception? the PickSaveFileAsync() ? Can you reproduce this with the minimum code? 🤔
— Reply to this email directly, view it on GitHub https://github.com/microsoft/WindowsAppSDK/issues/1188#issuecomment-1125666302, or unsubscribe https://github.com/notifications/unsubscribe-auth/AWPTXXLJBPEADQZWKSKGNI3VJXQ6BANCNFSM5BWB2JAQ. You are receiving this because you were mentioned.
@andrewleader thank you for the example. However when I click the button rapidly multiple folder picker launches. I am unable to make it so that it only launches once. What I want to achieve is the effect that we normally see, the picker window blinks when we try to launch another picker window. If you have any possible work around. Thank you for all your help.
Thanks. That's useful.
Just in case. Add a FileTypeFilter when using the FolderPicker. It works without the FileTypeFilter on a Windows 11, but you (might?) get a COMException on Windows 10.
FolderPicker folderPicker = new(); folderPicker.FileTypeFilter.Add("*"); IntPtr hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hwnd); StorageFolder folder = await folderPicker.PickSingleFolderAsync();
I still got COM exception on windows 11.
Just in case. Add a FileTypeFilter when using the FolderPicker. It works without the FileTypeFilter on a Windows 11, but you (might?) get a COMException on Windows 10.
FolderPicker folderPicker = new(); folderPicker.FileTypeFilter.Add("*"); IntPtr hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hwnd); StorageFolder folder = await folderPicker.PickSingleFolderAsync();
I still got COM exception on windows 11.
This is how you should do it
var FolderPicker = new FolderPicker
{
ViewMode = PickerViewMode.Thumbnail,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
var hwnd = App.MainWindow.GetWindowHandle();
WinRT.Interop.InitializeWithWindow.Initialize(FolderPicker, hwnd);
var folder = await FolderPicker.PickSingleFolderAsync();
At least, that is what worked to me
File picker is even easier since there is already a method that handle that part for you
string fileExtension = ".txt";
var FilePicker = App.MainWindow.CreateOpenFilePicker();
FilePicker.ViewMode = PickerViewMode.Thumbnail;
FilePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
FilePicker.FileTypeFilter.Add(fileExtension);
I'm using the function you mentioned in provided by WinUIEx, but it still give me error:
I'm using Windows 11 22000.795, .NET 6 with WinUI3 and build unpacked application.
@derekhe would you mind sharing more information about your project? Using Visual Studio 202022 17.3, WinAppSdk 1.1.3 and WinUiEx 1.7.0 on Windows 11 22000.856 in unpacked project I don't have this issue using the same exact code as you showed.
@TRadigk bro, are you running as administrator?
yes, my user is administrator.
Edit: you meant elevated - No, I don't start my app elevated.
Here is my sample project. I find it is caused by running it as administrator. As a normal user it is fine.
I'm using windows 11 22000.856.
My information vs 2022:
Microsoft Visual Studio Community 2022
Version 17.2.6
VisualStudio.17.Release/17.2.6+32630.192
Microsoft .NET Framework
Version 4.8.04161
Installed Version: Community
Visual C++ 2022 00482-90000-00000-AA897
Microsoft Visual C++ 2022
ASP.NET and Web Tools 2019 17.2.393.26812
ASP.NET and Web Tools 2019
Azure App Service Tools v3.0.0 17.2.393.26812
Azure App Service Tools v3.0.0
C# Tools 4.2.0-4.22281.5+8d3180e5f00d42f0f0295165f756f368f0cbfa44
C# components used in the IDE. Depending on your project type and settings, a different version of the compiler may be used.
Common Azure Tools 1.10
Provides common services for use by Azure Mobile Services and Microsoft Azure Tools.
IncrediBuild Build Acceleration 1.6.0.2
IncrediBuild effectively reduces compilation and development times by up to 90%.
Microsoft JVM Debugger 1.0
Provides support for connecting the Visual Studio debugger to JDWP compatible Java Virtual Machines
NuGet Package Manager 6.2.1
NuGet Package Manager in Visual Studio. For more information about NuGet, visit https://docs.nuget.org/
Razor (ASP.NET Core) 17.0.0.2218101+885a343b00bcab620a90c1550c37dafd730ce984
Provides languages services for ASP.NET Core Razor.
SQL Server Data Tools 17.0.62204.01010
Microsoft SQL Server Data Tools
Test Adapter for Boost.Test 1.0
Enables Visual Studio's testing tools with unit tests written for Boost.Test. The use terms and Third Party Notices are available in the extension installation directory.
Test Adapter for Google Test 1.0
Enables Visual Studio's testing tools with unit tests written for Google Test. The use terms and Third Party Notices are available in the extension installation directory.
TypeScript Tools 17.0.10418.2001
TypeScript Tools for Microsoft Visual Studio
Visual Basic Tools 4.2.0-4.22281.5+8d3180e5f00d42f0f0295165f756f368f0cbfa44
Visual Basic components used in the IDE. Depending on your project type and settings, a different version of the compiler may be used.
Visual F# Tools 17.1.0-beta.22329.1+702b8e77f5fbfe21e6743324c1750503e02f182d
Microsoft Visual F# Tools
Visual Studio IntelliCode 2.2
AI-assisted development for Visual Studio.
Since this issue is closed, I think it is worth re-opening it and point towards elevated support. I am able to repro the mentioned issue, but as far as I remember WinAppSdk had in the past, and I think still has trouble with elevated privileges (in regards of unpackaged apps). Maybe this topic is addressed in upcoming Community Call (August 17th)?
@TRadigk this is already opened by me some time ago: https://github.com/microsoft/WindowsAppSDK/issues/2504
I have seen several posts on how to use fileOpenPicker in WinUI3 but for me, the app does not even deploy successfully unless I remove the Declaration.
I always get the error: DEP0700: Registration of the app failed. [0x80073CF6] AppxManifest.xml(38,10): error 0x80070032: Cannot register the 82D57A91-4788-4329-A27B-168BB25CAFFC_1.0.0.0_x64__84fc1bza3khrr package because the following error was encountered while registering the windows.fileOpenPicker extension: The request is not supported.
Same thing happens with fileSavePicker. But the app run fine without both declarations.
The manifest file contains this:
Apparently, fileOpenPicker and fileSavePicker are only compatible with "uap"
It can work successfully in this way:
var picker = new FileOpenPicker();
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
var file = await picker.PickSingleFileAsync();
How to make it work win Page. Why MS so f.. this up. :( im so angry about this. Golden OpenFileDialog.. :(
How to make it work win Page. Why MS so f.. this up. :( im so angry about this. Golden OpenFileDialog.. :(
Your statement is not clear please.
What about Windows.Storage?
My solution is:
Window w = new();
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(w);
WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);
openPicker.SuggestedStartLocation = PickerLocationId.Desktop;
openPicker.FileTypeFilter.Add("*");
StorageFolder folder = await openPicker.PickSingleFolderAsync();
w.Close();
I have tried pretty much every solution suggested here and still get the System.Runtime.InteropServices.COMException on Windows 11 (222H2, 22621.2861 )
I have tried pretty much every solution suggested here and still get the System.Runtime.InteropServices.COMException on Windows 11 (222H2, 22621.2861 )
why don't you try the one showed on the WinUI 3 Gallery app?
<StackPanel VerticalAlignment="Top" Orientation="Horizontal">
<Button x:Name="PickAFileButton" Content="Open a file"
Click="PickAFileButton_Click" Margin="0,0,0,10"/>
<TextBlock x:Name="PickAFileOutputTextBlock" TextWrapping="Wrap" Padding="20,5,0,0"/>
</StackPanel>
private async void PickAFileButton_Click(object sender, RoutedEventArgs e)
{
// Clear previous returned file name, if it exists, between iterations of this scenario
OutputTextBlock.Text = "";
// Create a file picker
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
// Retrieve the window handle (HWND) of the current WinUI 3 window.
var window = WindowHelper.GetWindowForElement(this);
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
// Initialize the file picker with the window handle (HWND).
WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);
// Set options for your file picker
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.FileTypeFilter.Add("*");
// Open the picker for the user to pick a file
var file = await openPicker.PickSingleFileAsync();
if (file != null)
{
PickAFileOutputTextBlock.Text = "Picked file: " + file.Name;
}
else
{
PickAFileOutputTextBlock.Text = "Operation cancelled.";
}
}
@Guillermo-Santos Thank you for the tip. I copied your code to the barebone test app and copied WindowHelper.
Unfortunately, WindowHelper.GetWindowForElement(this)
returns null.
@Guillermo-Santos I realized the cause of the null problem. I changed the code to use WindowHelper.CreateWindow()
. Now, WindowHelper.GetWindowForElement(this)
returns non-null window. Unfortunately, var fileTest = await openPicker.PickSingleFileAsync()
still throws System.Runtime.InteropServices.COMException.
@Guillermo-Santos I realized the cause of the null problem. I changed the code to use
WindowHelper.CreateWindow()
. Now,WindowHelper.GetWindowForElement(this)
returns non-null window. Unfortunately,var fileTest = await openPicker.PickSingleFileAsync()
still throws System.Runtime.InteropServices.COMException.
I have not tested this code (xd), but i'll try and see if i have the same result. The only thing i could think that may bring this error is the target of the project (do not really know).
Using your modification throws with 'Access violation' to me, i think you can get rip of the WindowHelper class an intead use var window = App.MainWindow;
that one worked for me.
If you are using the blank template, then just add a property to the App class that expose the m_window
private field. and change the code to something like var window = ((App)Application.Current).MainWindow
.
Using your modification throws with 'Access violation' to me, i think you can get rip of the WindowHelper class an intead use
var window = App.MainWindow;
that one worked for me.
I realized that key is Window vs Page. Here is my code in App.cs:
public static Window? MainWindow { get; private set; }
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
MainWindow = WindowHelper.CreateWindow();
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (MainWindow.Content is not Frame rootFrame)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
// Place the frame in the current Window
MainWindow.Content = rootFrame;
rootFrame.NavigationFailed += OnNavigationFailed;
}
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), args.Arguments);
}
// Ensure the current window is active
MainWindow.Activate();
}
MainPage inherits Page, not Window.
This is mine:
public static Window MainWindow { get; private set; }
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
}
/// <summary>
/// Invoked when the application is launched.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
MainWindow = new MainWindow();
MainWindow.Activate();
}
As I say, you do not really need the WindowHelper. there should be a MainWindow.xaml
in your project, right? or are we using different templates?
This is mine: As I say, you do not really need the WindowHelper. there should be a
MainWindow.xaml
in your project, right? or are we using different templates?
I use a different template:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
}
Does this not work for an app that's running elevated? I keep getting a COMException with the error code 0x80004005 despite trying all of the solutions suggested in this thread. The code in my App.xaml.cs is the same as that posted by zipswich.
¿Esto no funciona para una aplicación que se ejecuta con privilegios elevados? Sigo recibiendo una COMException con el código de error 0x80004005 a pesar de probar todas las soluciones sugeridas en este hilo. El código en mi App.xaml.cs es el mismo que el publicado por zipswich
I think you should run your Visual Studio with administrator privileges, that helps your generated app inherit those privileges... If I'm not mistaken, if you set up your project correctly so that you have unlocked unlocked unsafe code executions, it shouldn't give you any problems
In desktop-based apps (like WinUI 3 desktop or WPF MSIX), The FileOpenPicker, FileSavePicker, and FolderPicker APIs require a HWND associated with them, so that they know which window to display over. That means, unlike UWP, you must add a couple extra lines of code before using the file and folder pickers.
Normally, the following works in UWP...
UWP
However, for desktop apps, you'll have to add two lines to obtain your current HWND, and set the HWND on the picker...
Desktop-based app
What about FileSavePicker and FolderPicker?
Same thing! Add those two lines.
More info on obtaining the HWND
One key thing to note about
GetWindowHandle(this)
, is that thethis
object you're passing must be a Window (either a WinUI 3 Window, a WPF Window, or a WinForms Window). If you're calling this code from your Window code-behind,this
will often work. If you're calling this code from another file, you're going to have to pass a reference of the window.Here's an example of a complete MainWindow using FileOpenPicker...
More info on interop
To learn more about these interop APIs, see https://docs.microsoft.com/windows/apps/desktop/modernize/winrt-com-interop-csharp