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?
CodePudding user response:
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.