### Using Dialog Service for Saving Presets Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Example of calling a strongly-typed dialog extension method to save a preset. ```csharp private async Task SavePreset() { var presetName = await dialogService.ShowSavePresetViewAsync(this); if (presetName != null) { ... } return presetName; } ``` -------------------------------- ### Custom DialogHost Extension Method Example Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Example of a custom extension method for IDialogService to show a text input dialog using DialogHost.Avalonia. It configures DialogHostSettings for a TextBoxViewModel. ```csharp public static async Task AskTextAsync(this IDialogService service, INotifyPropertyChanged ownerViewModel, AppDialogSettingsBase? appSettings = null) { if (ownerViewModel == null) throw new ArgumentNullException(nameof(ownerViewModel)); var vm = service.CreateViewModel(); var settings = new DialogHostSettings() { ContentViewModel = vm, CloseOnClickAway = true }; return (string?)await service.ShowDialogHostAsync(ownerViewModel, settings, appSettings); } ``` -------------------------------- ### StorageExtensions.ToDialog Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Converts Avalonia `IStorageFile` / `IStorageFolder` instances into MvvmDialogs `IDialogStorageFile` / `IDialogStorageFolder`. This enables cross-platform file-path usage as dialog start locations. ```APIDOC ## `StorageExtensions.ToDialog()` — Avalonia storage interop Converts Avalonia `IStorageFile` / `IStorageFolder` instances (obtained from `IStorageProvider`) into MvvmDialogs `IDialogStorageFile` / `IDialogStorageFolder`, enabling cross-platform file-path usage as dialog start locations. ### Usage Example: **Service class to resolve well-known folders:** ```csharp using Avalonia.Platform.Storage; using HanumanInstitute.MvvmDialogs.Avalonia; using HanumanInstitute.MvvmDialogs.FileSystem; public class StorageService : IStorageService { private IStorageProvider Storage => (Application.Current?.ApplicationLifetime switch { IClassicDesktopStyleApplicationLifetime d => d.MainWindow, ISingleViewApplicationLifetime s => TopLevel.GetTopLevel(s.MainView), _ => null })?.StorageProvider ?? throw new InvalidOperationException("No StorageProvider."); public async Task GetDownloadsFolderAsync() { var folder = await Storage.TryGetWellKnownFolderAsync(WellKnownFolder.Downloads); return folder?.ToDialog(); // IStorageFolder -> IDialogStorageFolder } } ``` **Using the converted folder as a SuggestedStartLocation:** ```csharp public async Task OpenFileAsync() { var settings = new OpenFileDialogSettings { SuggestedStartLocation = await _storage.GetDownloadsFolderAsync() }; var file = await _dialogService.ShowOpenFileDialogAsync(this, settings); if (file != null) Console.WriteLine(file.Path); // cross-platform URI } ``` ``` -------------------------------- ### Custom ViewLocator for Avalonia Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Implement a custom ViewLocator by inheriting from ViewLocatorBase to define how ViewModels are mapped to Views in Avalonia. This example customizes the naming convention. ```csharp using HanumanInstitute.MvvmDialogs.Avalonia; namespace MyDemoApp; /// /// Maps view models to views. /// public class ViewLocator : ViewLocatorBase { /// protected override string GetViewName(object viewModel) => viewModel.GetType().FullName!.Replace("ViewModel", ""); } ``` -------------------------------- ### Show Open File Dialog Async Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Use to display the system's open-file dialog for selecting a single file. Configure filters, suggested names, and starting locations. Returns an IDialogStorageFile or null if cancelled. ```csharp using HanumanInstitute.MvvmDialogs; using HanumanInstitute.MvvmDialogs.FileSystem; using HanumanInstitute.MvvmDialogs.FrameworkDialogs; using System.Reflection; using IOPath = System.IO.Path; public class MainWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; // Open a single file public async Task OpenSingleFileAsync() { var settings = new OpenFileDialogSettings { Title = "Open a text file", SuggestedStartLocation = new DesktopDialogStorageFolder( IOPath.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!), SuggestedFileName = "MyDocument", Filters = new List { new("Text Documents", "txt"), new("All Files", "*") } }; IDialogStorageFile? file = await _dialogService.ShowOpenFileDialogAsync(this, settings); if (file != null) { string path = file.LocalPath!; // desktop only // cross-platform: use file.Path (Uri), file.OpenReadAsync(), etc. } } // Open multiple files public async Task OpenMultipleFilesAsync() { var settings = new OpenFileDialogSettings { Filters = new List { new("Images", new[] { "png", "jpg", "gif" }), new("All Files", "*") } }; IReadOnlyList files = await _dialogService.ShowOpenFilesDialogAsync(this, settings); foreach (var file in files) Console.WriteLine(file.LocalPath); } // WPF-only synchronous variant public void OpenSync() { var result = _dialogService.ShowOpenFileDialog(this, new OpenFileDialogSettings()); } } ``` -------------------------------- ### Get Documents Folder Async Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Retrieves the Documents folder using the StorageProvider. Ensure a StorageProvider is available in the application lifetime. ```csharp public class StorageService : IStorageService { protected virtual IStorageProvider Storage => _storage ??= GetTopLevel()?.StorageProvider ?? throw new NullReferenceException("No StorageProvider found."); private IStorageProvider? _storage; public async Task GetDocumentsFolderAsync() { var result = await Storage.TryGetWellKnownFolderAsync(WellKnownFolder.Documents); return result?.ToDialog(); } private TopLevel? GetTopLevel() { if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { return desktop.MainWindow; } if (Application.Current?.ApplicationLifetime is ISingleViewApplicationLifetime viewApp) { var visualRoot = viewApp.MainView?.GetVisualRoot(); return visualRoot as TopLevel; } return null; } } ``` -------------------------------- ### Convert Avalonia Storage to MvvmDialogs Storage Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Use the ToDialog() extension method to convert Avalonia's IStorageFile/IStorageFolder to MvvmDialogs' IDialogStorageFile/IDialogStorageFolder. This enables cross-platform file path usage as dialog start locations. ```csharp using Avalonia.Platform.Storage; using HanumanInstitute.MvvmDialogs.Avalonia; using HanumanInstitute.MvvmDialogs.FileSystem; // Service class that resolves well-known folders cross-platform public class StorageService : IStorageService { private IStorageProvider Storage => (Application.Current?.ApplicationLifetime switch { IClassicDesktopStyleApplicationLifetime d => d.MainWindow, ISingleViewApplicationLifetime s => TopLevel.GetTopLevel(s.MainView), _ => null })?.StorageProvider ?? throw new InvalidOperationException("No StorageProvider."); public async Task GetDownloadsFolderAsync() { var folder = await Storage.TryGetWellKnownFolderAsync(WellKnownFolder.Downloads); return folder?.ToDialog(); // IStorageFolder -> IDialogStorageFolder } } // Use it as SuggestedStartLocation in any dialog public async Task OpenFileAsync() { var settings = new OpenFileDialogSettings { SuggestedStartLocation = await _storage.GetDownloadsFolderAsync() }; var file = await _dialogService.ShowOpenFileDialogAsync(this, settings); if (file != null) Console.WriteLine(file.Path); // cross-platform URI } ``` -------------------------------- ### Register IDialogService for Avalonia Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Register the `IDialogService` in your Avalonia application's `App.axaml.cs` using `Splat` for dependency injection. This setup is for Avalonia applications and requires `HanumanInstitute.MvvmDialogs.Avalonia`. ```csharp public override void Initialize() { AvaloniaXamlLoader.Load(this); Locator.CurrentMutable.RegisterLazySingleton(() => (IDialogService)new DialogService( new DialogManager(viewLocator: new ViewLocator()), viewModelFactory: x => Locator.Current.GetService(x))); SplatRegistrations.Register(); SplatRegistrations.Register(); SplatRegistrations.SetupIOC(); } ``` -------------------------------- ### Unit Test ViewModel with Mocked IDialogManager Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Unit test ViewModels without a UI by mocking IDialogManager. Configure the mock to set DialogResult and invoke callbacks to simulate user interaction. This example demonstrates testing dialogs and message boxes. ```csharp using Moq; using Xunit; using HanumanInstitute.MvvmDialogs; using HanumanInstitute.MvvmDialogs.Wpf; public class MainWindowViewModelTests { private object? ViewModelFactory(Type type) => type == typeof(AddTextDialogViewModel) ? new AddTextDialogViewModel() : null; public Mock MockDialogManager { get; } = new(); public DialogService DialogService => new DialogService(MockDialogManager.Object, viewModelFactory: ViewModelFactory); [Fact] public async Task ShowDialog_UserEntersText_AddsToList() { var model = new MainWindowViewModel(DialogService); const string newText = "Hello World"; // Simulate user typing text and clicking OK MockDialogManager .Setup(x => x.ShowDialogAsync( It.IsAny(), It.IsAny())) .Callback((_, vm) => { var dialogVm = (AddTextDialogViewModel)vm; dialogVm.Text = newText; dialogVm.DialogResult = true; }); await model.ShowDialogCommand.ExecuteAsync(null); Assert.Single(model.Texts); Assert.Equal(newText, model.Texts[0]); } [Fact] public async Task ShowMessageBox_UserConfirms_ReturnsTrue() { var model = new MainWindowViewModel(DialogService); MockDialogManager .Setup(x => x.ShowFrameworkDialogAsync( It.IsAny(), It.IsAny(), It.IsAny?>())) .ReturnsAsync(true); // simulate clicking Yes/OK await model.ConfirmActionCommand.ExecuteAsync(null); Assert.True(model.ActionConfirmed); } } ``` -------------------------------- ### Initialize Main Window in Avalonia App.axaml.cs Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Initialize the DialogService and display the main window. Ensure the MainWindowViewModel and IDialogService are accessible via the locator. ```csharp public override void OnFrameworkInitializationCompleted() { GC.KeepAlive(typeof(DialogService)); DialogService.Show(null, MainWindow); base.OnFrameworkInitializationCompleted(); } public static MainWindowViewModel MainWindow => Locator.Current.GetService()!; public static IDialogService DialogService => Locator.Current.GetService()!; ``` -------------------------------- ### Initialize Main Window in WPF App.xaml.cs Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Use IDialogService to create and show the main window ViewModel. Ensure the application's main window is correctly assigned after initialization. ```csharp protected override void OnStartup(StartupEventArgs e) { // ... var dialogService = Ioc.Default.GetRequiredService(); var vm = dialogService.CreateViewModel(); dialogService.Show(null, vm); Application.Current.MainWindow = Application.Current.Windows[0]; } ``` -------------------------------- ### Show Modal Dialog with IDialogService Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Demonstrates how to use IDialogService to create and show a dialog, handling the result and updating the ViewModel. ```csharp using HanumanInstitute.MvvmDialogs; public class ModalDialogTabContentViewModel : INotifyPropertyChanged { private readonly IDialogService dialogService; public ModalDialogTabContentViewModel(IDialogService dialogService) { this.dialogService = dialogService; } ... private async Task ShowDialogAsync() { var dialogViewModel = dialogService.CreateViewModel(); bool? success = await dialogService.ShowDialogAsync(this, dialogViewModel); if (success == true) { Texts.Add(dialogViewModel.Text); } } } ``` -------------------------------- ### StrongViewLocator Configuration Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Manually configure ViewModel-View pairs using `StrongViewLocator` to avoid issues with assembly trimming. ```APIDOC ## Configuring StrongViewLocator ### Description Manually register ViewModel-View pairs to ensure views are not trimmed during assembly trimming. ### Example Implementation ```csharp public class ViewLocator : StrongViewLocator { public ViewLocator() { Register(); Register(); Register(); } } ``` ### Usage Pass an instance of your `ViewLocator` to the `DialogManager`. ``` -------------------------------- ### Show Save File Dialog with Default Location Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Demonstrates how to use the StorageService to set the default location for a SaveFileDialog. Requires an instance of StorageService and IDialogService. ```csharp var _storage = new StorageService(); var settings = new SaveFileDialogSettings { SuggestedStartLocation = await _storage.GetDocumentsFolderAsync() }; var file = await _dialogService.ShowSaveFileDialogAsync(this, settings); ``` -------------------------------- ### IDialogService.ShowOpenFolderDialogAsync / ShowOpenFoldersDialogAsync Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Shows the system open-folder dialog. Returns IDialogStorageFolder (single) or IReadOnlyList (multiple). On Avalonia, cross-platform folder access is done via IDialogStorageFolder.Path (URI). ```APIDOC ## `IDialogService.ShowOpenFolderDialogAsync` / `ShowOpenFoldersDialogAsync` — Folder picker ### Description Shows the system open-folder dialog. Returns `IDialogStorageFolder` (single) or `IReadOnlyList` (multiple). On Avalonia, cross-platform folder access is done via `IDialogStorageFolder.Path` (URI). ### Method `async Task ShowOpenFolderDialogAsync(this INotifyPropertyChanged owner, OpenFolderDialogSettings settings)` `async Task> ShowOpenFoldersDialogAsync(this INotifyPropertyChanged owner, OpenFolderDialogSettings settings)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `OpenFolderDialogSettings` - Settings for the open folder dialog. ### Request Example ```csharp // Single folder var settings = new OpenFolderDialogSettings { Title = "Select output folder" }; IDialogStorageFolder? folder = await _dialogService.ShowOpenFolderDialogAsync(this, settings); // Multiple folders IReadOnlyList folders = await _dialogService.ShowOpenFoldersDialogAsync(this, new OpenFolderDialogSettings()); ``` ### Response #### Success Response (200) - `IDialogStorageFolder` (single folder picker) - `IReadOnlyList` (multiple folders picker) #### Response Example ```csharp // For single folder Console.WriteLine(folder.LocalPath); // desktop only // For multiple folders foreach (var folder in folders) Console.WriteLine(folder.Path); // Avalonia cross-platform ``` ``` -------------------------------- ### IDialogService.ShowOpenFileDialogAsync / ShowOpenFilesDialogAsync Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Shows the system open-file dialog. Returns an IDialogStorageFile (single) or IReadOnlyList (multiple). On desktop, .LocalPath gives the file path string. ```APIDOC ## `IDialogService.ShowOpenFileDialogAsync` / `ShowOpenFilesDialogAsync` — Open file picker ### Description Shows the system open-file dialog. Returns an `IDialogStorageFile` (single) or `IReadOnlyList` (multiple). On desktop, `.LocalPath` gives the file path string. ### Method `async Task ShowOpenFileDialogAsync(this INotifyPropertyChanged owner, OpenFileDialogSettings settings)` `async Task> ShowOpenFilesDialogAsync(this INotifyPropertyChanged owner, OpenFileDialogSettings settings)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `OpenFileDialogSettings` - Settings for the open file dialog. ### Request Example ```csharp var settings = new OpenFileDialogSettings { Title = "Open a text file", SuggestedStartLocation = new DesktopDialogStorageFolder( IOPath.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!), SuggestedFileName = "MyDocument", Filters = new List { new("Text Documents", "txt"), new("All Files", "*") } }; IDialogStorageFile? file = await _dialogService.ShowOpenFileDialogAsync(this, settings); ``` ### Response #### Success Response (200) - `IDialogStorageFile` (single file picker) - `IReadOnlyList` (multiple files picker) #### Response Example ```csharp // For single file string path = file.LocalPath!; // desktop only // cross-platform: use file.Path (Uri), file.OpenReadAsync(), etc. // For multiple files foreach (var file in files) Console.WriteLine(file.LocalPath); ``` ### Additional Notes - A synchronous variant `ShowOpenFileDialog` is available for WPF. ``` -------------------------------- ### Framework Dialogs Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Provides access to standard framework dialogs for message boxes, file selection, and folder selection. ```APIDOC ## Available Framework Dialog Methods ### Description `IDialogService` offers several methods for common dialog operations. ### Methods - `bool? ShowMessageBoxAsync` - `IDialogStorageFile? ShowOpenFileDialogAsync` - `IDialogStorageFile? ShowSaveFileDialogAsync` - `IDialogStorageFolder? ShowOpenFolderDialogAsync` - `IReadOnlyList ShowOpenFilesDialogAsync` - `IReadOnlyList ShowOpenFoldersDialogAsync` ### Notes on Return Types (v2+) - File and folder results are returned as `IDialogStorageFile` and `IDialogStorageFolder` respectively. - To get the local path as a string, use the `.LocalPath` property. Note that path formats may differ across platforms (mobile, web, desktop). ``` -------------------------------- ### Factory-Based ViewModel Creation with DI Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Use IDialogService.CreateViewModel with a viewModelFactory to create ViewModels via the DI container. This ensures proper dependency injection and testability. ```csharp // Registration in DI container new DialogService( dialogManager: new DialogManager(viewLocator: new ViewLocator()), viewModelFactory: x => Ioc.Default.GetService(x)) // delegate to DI container // Usage in ViewModel (factory resolves dependencies automatically) public async Task OpenPreferencesAsync() { // Creates PreferencesViewModel via DI — constructor injection handled automatically var vm = _dialogService.CreateViewModel(); vm.CurrentTheme = AppSettings.Theme; // configure before showing bool? saved = await _dialogService.ShowDialogAsync(this, vm); if (saved == true) ApplySettings(vm); } // Usage in unit tests — custom factory returns controllable instances private object? ViewModelFactory(Type type) => type switch { _ when type == typeof(AddTextDialogViewModel) => new AddTextDialogViewModel(), _ when type == typeof(PreferencesViewModel) => new PreferencesViewModel(mockSettings), _ => null }; ``` -------------------------------- ### Show Message Box with Caption and Buttons Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Configures the message box with a title and specific buttons (e.g., Yes/No). Handles user confirmation. ```csharp public class MainWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; public async Task ConfirmDelete() { bool? result = await _dialogService.ShowMessageBoxAsync( this, "Are you sure you want to delete this file?", "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == true) { /* delete */ } } } ``` -------------------------------- ### Run UI Method Asynchronously Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Utilize the RunUiAsync extension method from HanumanInstitute.MvvmDialogs.Wpf or HanumanInstitute.MvvmDialogs.Avalonia to execute synchronous UI methods asynchronously. ```csharp UiExtensions.RunUiAsync(func) ``` -------------------------------- ### Strongly-Typed Dialog Extensions for Loading Presets Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Provides extension methods for IDialogService to show a load preset dialog, returning the selected item if successful. Requires HanumanInstitute.Validators. ```csharp public static class DialogExtensions { public static async Task ShowLoadPresetViewAsync(this IDialogService dialog, INotifyPropertyChanged ownerViewModel) { dialog.CheckNotNull(nameof(dialog)); // using HanumanInstitute.Validators var viewModel = dialog.CreateViewModel(); viewModel.Load(false); var result = await dialog.ShowDialogAsync(ownerViewModel, viewModel).ConfigureAwait(true); return result == true ? viewModel.SelectedItem : null; } } ``` -------------------------------- ### Create Custom Dialog Factory Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Implement a custom dialog factory by inheriting from DialogFactoryBase and overriding ShowDialogAsync to handle specific dialog settings. Use base.ShowDialogAsync for unhandled types. ```csharp public class CustomDialogFactory : DialogFactoryBase { public CustomDialogFactory(IDialogFactory? chain = null) : base(chain) { } public override async Task ShowDialogAsync(WindowWrapper owner, TSettings settings, AppDialogSettings appSettings) => settings switch { OpenFolderDialogSettings s => await ShowOpenFolderDialogAsync(owner, s, appSettings), _ => base.ShowDialogAsync(owner, settings, appSettings) }; private async Task ShowOpenFolderDialogAsync(WindowWrapper owner, OpenFolderDialogSettings settings, AppDialogSettings appSettings) => "Action here"; } ``` -------------------------------- ### Show Save File Dialog Async Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Use to display the system's save-file dialog for choosing a destination. Configure title, suggested file name, default extension, and filters. Returns an IDialogStorageFile or null if cancelled. ```csharp using HanumanInstitute.MvvmDialogs; using HanumanInstitute.MvvmDialogs.FrameworkDialogs; public class MainWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; public async Task SaveFileAsync() { var settings = new SaveFileDialogSettings { Title = "Save Report", SuggestedFileName = "report", DefaultExtension = ".txt", Filters = new List { new("Text Documents", "txt"), new("CSV Files", "csv"), new("All Files", "*") } }; IDialogStorageFile? file = await _dialogService.ShowSaveFileDialogAsync(this, settings); if (file != null) { string path = file.LocalPath!; await using var stream = await file.OpenWriteAsync(); // write to stream } } } ``` -------------------------------- ### Register Avalonia Dialog Providers with DialogFactory Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Use extension methods like AddMessageBox, AddFluent, and AddDialogHost to register dialog providers with the IDialogFactory. This allows for cross-platform message boxes, WinUI-style dialogs, and overlay dialogs. ```csharp using HanumanInstitute.MvvmDialogs; using HanumanInstitute.MvvmDialogs.Avalonia; using HanumanInstitute.MvvmDialogs.Avalonia.Fluent; // MessageBox.Avalonia — cross-platform message boxes new DialogService(new DialogManager( dialogFactory: new DialogFactory().AddMessageBox(MessageBoxMode.Popup))) // Popup = cross-platform // FluentAvalonia — WinUI-style ContentDialog and TaskDialog new DialogService(new DialogManager( dialogFactory: new DialogFactory().AddFluent(FluentMessageBoxType.ContentDialog))) // Then call the extra methods from ViewModel: public async Task ShowFluentDialog() { var result = await _dialogService.ShowContentDialogAsync(this, new ContentDialogSettings { Content = "Save changes?", PrimaryButtonText = "Save", SecondaryButtonText = "Don't Save", CloseButtonText = "Cancel", DefaultButton = FAContentDialogButton.Primary }); // result is FAContentDialogResult.Primary / Secondary / None var taskResult = await _dialogService.ShowTaskDialogAsync(this, new TaskDialogSettings()); } // DialogHost.Avalonia — overlay popup dialogs new DialogService(new DialogManager( dialogFactory: new DialogFactory().AddDialogHost())) public async Task ShowOverlayDialog() { var vm = _dialogService.CreateViewModel(); var settings = new DialogHostSettings { Content = vm, CloseOnClickAway = true, CloseOnClickAwayParameter = null }; object? result = await _dialogService.ShowDialogHostAsync(this, settings); } ``` -------------------------------- ### Show Open Folder Dialog Async Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Use to display the system's open-folder dialog for selecting a single folder. Configure the dialog title. Returns an IDialogStorageFolder or null if cancelled. ```csharp using HanumanInstitute.MvvmDialogs; using HanumanInstitute.MvvmDialogs.FrameworkDialogs; public class MainWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; // Single folder public async Task PickFolderAsync() { var settings = new OpenFolderDialogSettings { Title = "Select output folder" }; IDialogStorageFolder? folder = await _dialogService.ShowOpenFolderDialogAsync(this, settings); if (folder != null) Console.WriteLine(folder.LocalPath); // desktop only } // Multiple folders public async Task PickMultipleFoldersAsync() { IReadOnlyList folders = await _dialogService.ShowOpenFoldersDialogAsync(this, new OpenFolderDialogSettings()); foreach (var folder in folders) Console.WriteLine(folder.Path); } } ``` -------------------------------- ### Show Message Box with Settings Object Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Uses a MessageBoxSettings object for detailed configuration including content, title, buttons, icon, and default selection. ```csharp public class MainWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; public async Task ShowCustomMessageBox() { var settings = new MessageBoxSettings { Content = "Proceed with the operation?", Title = "Confirmation", Button = MessageBoxButton.OkCancel, Icon = MessageBoxImage.Question, DefaultValue = true // OK is pre-selected }; bool? result = await _dialogService.ShowMessageBoxAsync(this, settings); } } ``` -------------------------------- ### Avalonia ViewLocator for Single-Page Navigation Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Forces single-page navigation mode on desktop by setting the ForceSinglePageNavigation property. ```csharp // Force single-page navigation mode even on desktop public class ViewLocator : ViewLocatorBase { public ViewLocator() => ForceSinglePageNavigation = true; } ``` -------------------------------- ### ViewModel Factory with DialogService Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Provide a viewModelFactory to the DialogService constructor to handle dependency injection for view models. Use dialogService.CreateViewModel to instantiate view models. ```csharp new DialogService(viewModelFactory: x => Locator.Current.GetService(x)) ``` -------------------------------- ### Strongly-Typed Dialog Extensions for Saving Presets Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Provides extension methods for IDialogService to show a save preset dialog, returning the preset name if successful. Requires HanumanInstitute.Validators. ```csharp public static class DialogExtensions { public static async Task ShowSavePresetViewAsync(this IDialogService dialog, INotifyPropertyChanged ownerViewModel) { dialog.CheckNotNull(nameof(dialog)); var viewModel = dialog.CreateViewModel(); viewModel.Load(true); var result = await dialog.ShowDialogAsync(ownerViewModel, viewModel).ConfigureAwait(true); return result == true ? viewModel.PresetName : null; } } ``` -------------------------------- ### Show Synchronous Dialog in WPF Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Demonstrates showing a dialog synchronously using the IDialogService in a WPF application. This method is WPF-specific and should be avoided if cross-framework compatibility is needed. ```csharp private bool? ShowDialog() { var dialogViewModel = dialogService.CreateViewModel(); return dialogService.ShowDialog(this, dialogViewModel); // Sync } } ``` -------------------------------- ### AddMessageBox, AddFluent, AddDialogHost Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Factory extension methods to register optional dialog providers for Avalonia applications. These methods allow integration of cross-platform message boxes, WinUI-style dialogs, and overlay dialogs. ```APIDOC ## `.AddMessageBox()` / `.AddFluent()` / `.AddDialogHost()` — Extension dialog providers Factory extension methods that register optional dialog providers in the `IDialogFactory` chain for Avalonia applications. ### Usage Examples: **MessageBox.Avalonia — cross-platform message boxes** ```csharp new DialogService(new DialogManager( dialogFactory: new DialogFactory().AddMessageBox(MessageBoxMode.Popup))) ``` **FluentAvalonia — WinUI-style ContentDialog and TaskDialog** ```csharp new DialogService(new DialogManager( dialogFactory: new DialogFactory().AddFluent(FluentMessageBoxType.ContentDialog))) ``` **DialogHost.Avalonia — overlay popup dialogs** ```csharp new DialogService(new DialogManager( dialogFactory: new DialogFactory().AddDialogHost())) ``` ### ViewModel Usage Examples: **Showing a Fluent Avalonia dialog:** ```csharp public async Task ShowFluentDialog() { var result = await _dialogService.ShowContentDialogAsync(this, new ContentDialogSettings { Content = "Save changes?", PrimaryButtonText = "Save", SecondaryButtonText = "Don't Save", CloseButtonText = "Cancel", DefaultButton = FAContentDialogButton.Primary }); // result is FAContentDialogResult.Primary / Secondary / None var taskResult = await _dialogService.ShowTaskDialogAsync(this, new TaskDialogSettings()); } ``` **Showing an overlay dialog:** ```csharp public async Task ShowOverlayDialog() { var vm = _dialogService.CreateViewModel(); var settings = new DialogHostSettings { Content = vm, CloseOnClickAway = true, CloseOnClickAwayParameter = null }; object? result = await _dialogService.ShowDialogHostAsync(this, settings); } ``` ``` -------------------------------- ### Show Modal Dialog with Custom ViewModel Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Implement IModalDialogViewModel and ICloseable in your dialog ViewModel. The owner ViewModel awaits the dialog result. ```csharp public class AddTextDialogViewModel : ObservableObject, IModalDialogViewModel, ICloseable { private string? _text; private bool? _dialogResult; public string? Text { get => _text; set => SetProperty(ref _text, value); } public bool? DialogResult { get => _dialogResult; set => SetProperty(ref _dialogResult, value); } public event EventHandler? RequestClose; public ICommand OkCommand => new RelayCommand(Ok); private void Ok() { if (!string.IsNullOrEmpty(Text)) { DialogResult = true; RequestClose?.Invoke(this, EventArgs.Empty); // closes the view } } } public class MainWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; public ObservableCollection Texts { get; } public MainWindowViewModel(IDialogService dialogService) => _dialogService = dialogService; public async Task ShowDialogAsync() { var dialogViewModel = _dialogService.CreateViewModel(); bool? success = await _dialogService.ShowDialogAsync(this, dialogViewModel); if (success == true) { Texts.Add(dialogViewModel.Text!); } } public async Task ShowDialogExplicitAsync() { var dialogViewModel = _dialogService.CreateViewModel(); bool? success = await _dialogService.ShowDialogAsync(this, dialogViewModel); } } ``` -------------------------------- ### Enable Dialog Logging Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md To enable logging for dialogs, create a DialogManager instance and pass an ILogger to its constructor, typically obtained from a LoggerFactory. ```csharp var loggerFactory = LoggerFactory.Create(builder => builder.AddDebug()); var dialogService = new DialogService( new DialogManager(logger: loggerFactory.CreateLogger())); ``` -------------------------------- ### IDialogService.ShowMessageBoxAsync Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Shows a message box with configurable text, title, buttons, and icon. Returns true for OK/Yes, false for No, and null for Cancel. ```APIDOC ## IDialogService.ShowMessageBoxAsync — Show a message box ### Description Extension method that shows a message box with configurable text, title, buttons, and icon. Returns `true` for OK/Yes, `false` for No, and `null` for Cancel. ### Method Signatures ```csharp Task ShowMessageBoxAsync(object ownerViewModel, string message, string caption = "", MessageBoxButton buttons = MessageBoxButton.Ok, MessageBoxImage icon = MessageBoxImage.None) Task ShowMessageBoxAsync(object ownerViewModel, MessageBoxSettings settings) ``` ### Parameters #### Path Parameters - **ownerViewModel** (object) - The owner ViewModel. - **message** (string) - The message content to display. - **caption** (string, optional) - The title of the message box. Defaults to "". - **buttons** (MessageBoxButton, optional) - The buttons to display. Defaults to `MessageBoxButton.Ok`. - **icon** (MessageBoxImage, optional) - The icon to display. Defaults to `MessageBoxImage.None`. - **settings** (MessageBoxSettings) - An object containing detailed settings for the message box. ### Request Example ```csharp // Simple message public async Task ShowSimpleMessage() => await _dialogService.ShowMessageBoxAsync(this, "File saved successfully."); // With caption and buttons public async Task ConfirmDelete() { bool? result = await _dialogService.ShowMessageBoxAsync( this, "Are you sure you want to delete this file?", "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == true) { /* delete */ } } // Using explicit settings object public async Task ShowCustomMessageBox() { var settings = new MessageBoxSettings { Content = "Proceed with the operation?", Title = "Confirmation", Button = MessageBoxButton.OkCancel, Icon = MessageBoxImage.Question, DefaultValue = true // OK is pre-selected }; bool? result = await _dialogService.ShowMessageBoxAsync(this, settings); } // WPF-only synchronous variant public void ShowSync() { bool? result = _dialogService.ShowMessageBox(this, "Done!", "Info"); } ``` ### Response #### Success Response - **bool?**: `true` for OK/Yes, `false` for No, `null` for Cancel. ``` -------------------------------- ### Define StrongViewLocator for ViewModel-View Mapping Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Configure ViewModel-View pairs manually using StrongViewLocator to avoid reflection-based resolution and support Assembly Trimming. Register concrete ViewModel, View, and Window types. ```csharp public class ViewLocator : StrongViewLocator { public ViewLocator() { Register() Register() Register(); } } ``` -------------------------------- ### DialogHost.Avalonia Integration Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Integrates DialogHost.Avalonia for displaying views as popup overlays, providing full control over the dialog's appearance and behavior. ```APIDOC ## Registering DialogHost.Avalonia Handlers ### Description Register dialog handlers for DialogHost.Avalonia to enable `ShowDialogHostAsync`. ### Method ```csharp new DialogService(new DialogManager(dialogFactory: new DialogFactory().AddDialogHost())) ``` ### Supported Settings for `ShowDialogHostAsync` - **ContentViewModel**: The ViewModel of the view to display. Resolved via Avalonia's ViewLocator. - **ClosingHandler**: A callback to potentially cancel the closing of the view. - **CloseOnClickAway**: Boolean to determine if clicking outside the dialog closes it. - **CloseOnClickAwayParameter**: The value to return when closing by clicking away. - **PopupPositioner**: A class to customize the dialog's positioning. ``` ```APIDOC ## Custom Extension Method for DialogHost ### Description An example of creating a custom extension method for `IDialogService` to show a text input dialog using DialogHost. ### Method Signature ```csharp public static async Task AskTextAsync(this IDialogService service, INotifyPropertyChanged ownerViewModel, AppDialogSettingsBase? appSettings = null) ``` ### Usage Example ```csharp var vm = service.CreateViewModel(); var settings = new DialogHostSettings() { ContentViewModel = vm, CloseOnClickAway = true }; return (string?)await service.ShowDialogHostAsync(ownerViewModel, settings, appSettings); ``` ``` -------------------------------- ### Register Dialog Factory with DialogService Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Instantiate DialogService with a chained DialogFactory, including your custom factory, to handle specific dialog types while falling back to default implementations for others. ```csharp new DialogService(dialogManager: new DialogManager( dialogFactory: new DialogFactory().AddCustomOpenFolder())) ``` -------------------------------- ### Avalonia Default ViewLocator Convention Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Uses naming conventions to map ViewModels to Views. The default convention replaces 'ViewModels' with 'Views' and 'ViewModel' with 'Window' or 'View'. Override GetViewName for custom logic. ```csharp using HanumanInstitute.MvvmDialogs.Avalonia; // Default Avalonia ViewLocator (convention-based) // MyApp.ViewModels.MainViewModel -> MyApp.Views.MainWindow (desktop) // MyApp.ViewModels.MainViewModel -> MyApp.Views.MainView (mobile/navigation) public class ViewLocator : ViewLocatorBase { // Override to use a custom naming convention protected override string GetViewName(object viewModel) => viewModel.GetType().FullName! .Replace(".ViewModels.", ".Views.") .Replace("ViewModel", ""); } ``` -------------------------------- ### Show Simple Message Box Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Displays a basic message box with only content. Use this for simple notifications. ```csharp using HanumanInstitute.MvvmDialogs; using HanumanInstitute.MvvmDialogs.FrameworkDialogs; public class MainWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; public async Task ShowSimpleMessage() => await _dialogService.ShowMessageBoxAsync(this, "File saved successfully."); } ``` -------------------------------- ### Register Custom Dialog Factory Extension Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Create an extension method to simplify the registration of your custom dialog factory within the dialog service chain. ```csharp public static class DialogFactoryExtensions { public static IDialogFactory AddCustomOpenFolder(this IDialogFactory factory) => new CustomDialogFactory(factory); } ``` -------------------------------- ### IDialogService.ShowDialogAsync Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Displays a modal dialog and awaits its result. The ViewModel must implement IModalDialogViewModel to expose DialogResult. Returns true for OK/Yes, false for No, and null for Cancel. ```APIDOC ## IDialogService.ShowDialogAsync — Display a modal dialog ### Description Shows a modal dialog and awaits its result. The ViewModel must implement `IModalDialogViewModel` to expose `DialogResult`. Returns `true` for OK/Yes, `false` for No, and `null` for Cancel. ### Method Signature ```csharp Task ShowDialogAsync(object ownerViewModel, T viewModel) ``` ### Parameters #### Path Parameters - **ownerViewModel** (object) - The owner ViewModel. - **viewModel** (T) - The dialog ViewModel. Must implement `IModalDialogViewModel`. ### Request Example ```csharp // Owner ViewModel calling the modal dialog public class MainWindowViewModel : ObservableObject { private readonly IDialogService _dialogService; public ObservableCollection Texts { get; } = new(); public MainWindowViewModel(IDialogService dialogService) => _dialogService = dialogService; public async Task ShowDialogAsync() { var dialogViewModel = _dialogService.CreateViewModel(); bool? success = await _dialogService.ShowDialogAsync(this, dialogViewModel); if (success == true) { Texts.Add(dialogViewModel.Text!); } } // Explicitly specify the view type (bypasses locator) public async Task ShowDialogExplicitAsync() { var dialogViewModel = _dialogService.CreateViewModel(); bool? success = await _dialogService.ShowDialogAsync(this, dialogViewModel); } } ``` ### Response #### Success Response - **bool?**: `true` for OK/Yes, `false` for No, `null` for Cancel. ``` -------------------------------- ### Run Synchronous UI Work Asynchronously Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Use UiExtensions.RunUiAsync to schedule a synchronous UI-thread callback and return a Task. This is useful for running blocking dialog code from a background thread or async context without blocking the main thread. ```csharp using HanumanInstitute.MvvmDialogs.Avalonia; // or HanumanInstitute.MvvmDialogs.Wpf for WPF // Run blocking dialog on UI thread from a background thread or async context public async Task PromptUserForInput() { return await UiExtensions.RunUiAsync(() => { // This lambda runs on the UI thread var inputDialog = new MyInputDialog(); inputDialog.ShowDialog(); return inputDialog.Result; }); } // Typical usage inside a custom DialogFactory method public override async Task ShowDialogAsync(IView? owner, TSettings settings) => settings switch { MyCustomSettings s => await UiExtensions.RunUiAsync(() => ShowMyCustomDialog(owner, s)), _ => base.ShowDialogAsync(owner, settings) }; ``` -------------------------------- ### Configure MessageBox in Avalonia Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Configure the DialogService to use the MessageBox.Avalonia extension for handling message box requests. Use MessageBoxMode.Popup for cross-platform compatibility. ```csharp new DialogService(new DialogManager(dialogFactory: new DialogFactory().AddMessageBox(MessageBoxMode.Popup))) ``` -------------------------------- ### Implement ViewModel Lifecycle Hooks Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Implement IViewLoaded, IViewClosing, and IViewClosed interfaces in your ViewModel to receive view lifecycle events. Use OnClosingAsync for async confirmation dialogs before closing. ```csharp using System.ComponentModel; using HanumanInstitute.MvvmDialogs; using HanumanInstitute.MvvmDialogs.FrameworkDialogs; using CommunityToolkit.Mvvm.ComponentModel; public class MainWindowViewModel : ObservableObject, IViewLoaded, IViewClosing, IViewClosed { private readonly IDialogService _dialogService; public MainWindowViewModel(IDialogService dialogService) => _dialogService = dialogService; // Called when the view finishes loading public void OnLoaded() { Console.WriteLine("View is ready — load initial data here."); } // Called synchronously when closing starts; set e.Cancel=true to trigger async confirmation public void OnClosing(CancelEventArgs e) { e.Cancel = true; // block immediate close, go to OnClosingAsync } // Called after e.Cancel=true in OnClosing; set e.Cancel=false to allow closing public async Task OnClosingAsync(CancelEventArgs e) { bool? quit = await _dialogService.ShowMessageBoxAsync( this, "Do you really want to quit?", "Confirmation", MessageBoxButton.YesNo); e.Cancel = quit != true; // allow close only on Yes } // Called after the view is fully closed public void OnClosed() { // Unsubscribe events, release resources Console.WriteLine("View closed — cleanup here."); } } ``` -------------------------------- ### Custom ViewLocator for WPF Source: https://github.com/mysteryx93/hanumaninstitute.mvvmdialogs/blob/master/README.md Defines a custom ViewLocator that inherits from ViewLocatorBase to map ViewModels to Views using a specific naming convention. ```csharp using HanumanInstitute.MvvmDialogs.Wpf; namespace MyDemoApp; /// /// Maps view models to views. /// public class ViewLocator : ViewLocatorBase { /// protected override string GetViewName(object viewModel) => viewModel.GetType().FullName!.Replace("ViewModel", "View"); } ``` -------------------------------- ### IDialogService.ShowSaveFileDialogAsync Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Shows the system save-file dialog. Returns an IDialogStorageFile pointing to the chosen destination, or null if the user cancelled. ```APIDOC ## `IDialogService.ShowSaveFileDialogAsync` — Save file picker ### Description Shows the system save-file dialog. Returns an `IDialogStorageFile` pointing to the chosen destination, or `null` if the user cancelled. ### Method `async Task ShowSaveFileDialogAsync(this INotifyPropertyChanged owner, SaveFileDialogSettings settings)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `SaveFileDialogSettings` - Settings for the save file dialog. ### Request Example ```csharp var settings = new SaveFileDialogSettings { Title = "Save Report", SuggestedFileName = "report", DefaultExtension = ".txt", Filters = new List { new("Text Documents", "txt"), new("CSV Files", "csv"), new("All Files", "*") } }; IDialogStorageFile? file = await _dialogService.ShowSaveFileDialogAsync(this, settings); ``` ### Response #### Success Response (200) - `IDialogStorageFile?` - An object representing the chosen file, or null if cancelled. #### Response Example ```csharp if (file != null) { string path = file.LocalPath!; await using var stream = await file.OpenWriteAsync(); // write to stream } ``` ``` -------------------------------- ### UiExtensions.RunUiAsync Source: https://context7.com/mysteryx93/hanumaninstitute.mvvmdialogs/llms.txt Schedules a synchronous UI-thread callback and returns a `Task` that completes when the callback finishes. This is useful for running blocking dialog code without blocking the calling thread, typically within custom `DialogFactory` implementations. ```APIDOC ## `UiExtensions.RunUiAsync` — Run synchronous UI work as async Schedules a synchronous UI-thread callback and returns a `Task` that completes when the callback finishes. Used inside custom `DialogFactory` implementations to run blocking dialog code without blocking the calling thread. ### Usage Examples: **Prompting user for input from a background thread:** ```csharp using HanumanInstitute.MvvmDialogs.Avalonia; // or HanumanInstitute.MvvmDialogs.Wpf for WPF public async Task PromptUserForInput() { return await UiExtensions.RunUiAsync(() => { // This lambda runs on the UI thread var inputDialog = new MyInputDialog(); inputDialog.ShowDialog(); return inputDialog.Result; }); } ``` **Typical usage inside a custom DialogFactory method:** ```csharp public override async Task ShowDialogAsync(IView? owner, TSettings settings) => settings switch { MyCustomSettings s => await UiExtensions.RunUiAsync(() => ShowMyCustomDialog(owner, s)), _ => base.ShowDialogAsync(owner, settings) }; ``` ```