Hi @Eduardo Gomez ,
Thanks for reaching out.
The FolderPicker in WinUI 3 needs to be initialized with a window handle before you can call PickSingleFolderAsync(). Without this, you'll get that COMException: Invalid window handle (0x80070578) error.
The tricky part here is that your BuildPageViewModel is sitting inside a page that's hosted in a frame, so it doesn't have direct access to the main window. To solve this while keeping your MVVM architecture clean, I'd recommend creating a simple service that provides the window handle to any component that needs it.
What I'd do is:
- Create an interface for the window service
Create Interfaces/IWindowService.cs:
namespace EasyShere.Interface;
public interface IWindowService {
nint GetWindowHandle();
}
- Implement the service
Create Services/WindowService.cs:
using EasyShere.Interface;
namespace EasyShere.Services;
public class WindowService : IWindowService {
private nint _windowHandle;
public void Initialize(Window window) {
_windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(window);
}
public nint GetWindowHandle() {
if(_windowHandle == 0) {
throw new InvalidOperationException("Window handle not initialized. Call Initialize() first.");
}
return _windowHandle;
}
}
- Register it in your DI container
Update App.xaml.cs in the ConfigureServices method:
services.AddSingleton<WindowService>();
services.AddSingleton<IWindowService>(sp => sp.GetRequiredService<WindowService>());
- Initialize it when the app launches
In App.xaml.cs, update the OnLaunched method:
protected override void OnLaunched(LaunchActivatedEventArgs args) {
_window = Services.GetRequiredService<MainWindow>();
var windowService = Services.GetRequiredService<WindowService>();
windowService.Initialize(_window);
_window.ExtendsContentIntoTitleBar = true;
_window.Activate();
}
- Use it in your ViewModel
Update BuildPageViewModel.cs:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using EasyShere.Interface;
using System.Threading.Tasks;
using FolderPicker = Windows.Storage.Pickers.FolderPicker;
namespace EasyShere.ViewModel;
public partial class BuildPageViewModel : ObservableObject {
private readonly IWindowService _windowService;
public BuildPageViewModel(IWindowService windowService) {
_windowService = windowService;
}
[ObservableProperty]
public partial bool IsButtonEnabled { get; set; } = true;
[ObservableProperty]
public partial string Path { get; set; }
[RelayCommand]
async Task OpenFolder() {
var folderPicker = new FolderPicker();
var hwnd = _windowService.GetWindowHandle();
WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hwnd);
var FolderLocation = await folderPicker.PickSingleFolderAsync();
if(FolderLocation != null) {
Path = FolderLocation.Path;
}
}
}
Hope this helps! If my answer was helpful - kindly follow the instructions here so others with the same problem can benefit as well.