2

I'm building an app for windows only, that needs to consume a docx file using .net MAUI.

I use the suggested class IFilePicker, implemented it, and worked fine while debugging (both in debug and release mode).

So, after finished a preview version, I want to deploy unpacked, "like a portable version", using:

MSBuild.exe D:\Workspace\dotNet\WordReplacer\WordReplacer.App\ /restore /t:Publish /p:TargetFramework=net6.0-windows10.0.19041 /p:configuration=release /p:WindowsAppSDKSelfContained=true /p:Platform=x64 /p:PublishSingleFile=true /p:WindowsPackageType=None /p:RuntimeIdentifier=win10-x64

Everthing works fine just as debug, except for the FilePicker that doesn't work and gives me the error:

Value does not fall within the expected range

This error doesn't happen if I install a published package with a certificate. So maybe I'm missing something in the msbuilder workaround to generate an unpacked app.

I'm using the communitytoolkit.MVVM and the method that I use to pick the file stays in my viewmodel:

        private string _inputFilePath;
        
        [ObservableProperty]
        private string _inputFileNameText = "Select a input file";
        
        [RelayCommand]
        public async Task PickInputDocAsync()
        {
            try
            {
                var customFileType = new FilePickerFileType(
                    new Dictionary<DevicePlatform, IEnumerable<string>>
                    {
                        { DevicePlatform.WinUI, new[] { ".doc", ".docx" } },
                    });

                PickOptions options = new()
                {
                    PickerTitle = "Please select a document",
                    FileTypes = customFileType,
                };

                var result = await FilePicker.Default.PickAsync(options).ConfigureAwait(false);

                if (result != null)
                {
                    _inputFilePath = result.FullPath;
                    InputFileNameText = result.FileName;
                }

            }
            catch (Exception ex)
            {
                ErrorMessage = $"{ex.InnerException?.Message} Error: {ex.Message}, InputFilePath: {_inputFilePath}, InputFileName: {InputFileNameText}";
            }

Any clue how to fix it?

Adley
  • 511
  • 1
  • 6
  • 19

1 Answers1

1

I've been trying to fix this error, but since I don't know much about msbuild itself, I take another approach.

So, I finally got it working when I implemented a FilePicker specifically for the Windows platform.

I take most of the code from this answer Folder Picker .NET MAUI, but, instead of folderpicker I use the filepicker. Check it out to know more about the implementation and the set up.

How I do it:

Create a Folder helper in the root folder app and create an interface ICustomPicker and a data transfer object(DTO).

public interface ICustomPicker
{
    Task<FileDto> PickFileAsync();
}
public class FileDto
{
    public string DisplayName { get; set; }
    public string Name { get; set; }
    public string FullPath { get; set; }
}

Inside the Plataforms/Windows folder I created CustomFilePicker.cs

public class CustomPicker : ICustomPicker
{
    
     public async Task<FileDto> PickFileAsync()
        {
            try
            {
                var picker = new WindowsFilePicker();

                picker.FileTypeFilter.Add(".docx");
                picker.FileTypeFilter.Add(".doc");

                // Get the current window's HWND by passing in the Window object
                var windowHandle = ((MauiWinUIWindow)App.Current.Windows[0].Handler.PlatformView).WindowHandle;

                // Associate the HWND - window handler, with the file picker
                WinRT.Interop.InitializeWithWindow.Initialize(picker, windowHandle);

                var storageFile = await picker.PickSingleFileAsync();

                if (storageFile != null)
                {
                    return new FileDto()
                    {
                        DisplayName = storageFile.DisplayName,
                        Name = storageFile.Name,
                        FullPath = storageFile.Path
                    };
                }
            }
            catch
            {
                // Ignored
            }
            return null;

        }
}

Register the DI in my MauiProgram.cs

#if WINDOWS
            builder.Services.AddTransient<ICustomPicker, Platforms.Windows.CustomPicker>();
#endif

then in my view model I simply call it


private readonly ICustomPicker _customPicker;
public MainViewModel(ICustomPicker customPicker,)
{        
    _customPicker = customPicker;         
}

[RelayCommand]
public async Task PickInputDocAsync(){

    var file = await _customPicker.PickFileAsync().ConfigureAwait(false);

    if (file != null)
    {
        //do something
    }
}

Probably this problem will disappear (I hope) when MAUI releases a proper unpacked publish option.

Note: Right now, I just test this approach in Windows 11.

Adley
  • 511
  • 1
  • 6
  • 19