diff --git a/Directory.Packages.props b/Directory.Packages.props index e913b828d..3fde8c6c3 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -61,14 +61,14 @@ - - - - - - - - + + + + + + + + diff --git a/e2e/Avalonia/PrismAvaloniaDemo.slnx b/e2e/Avalonia/PrismAvaloniaDemo.slnx index e572cd053..77bc2e04c 100644 --- a/e2e/Avalonia/PrismAvaloniaDemo.slnx +++ b/e2e/Avalonia/PrismAvaloniaDemo.slnx @@ -5,5 +5,11 @@ + + + + + + diff --git a/e2e/Avalonia/PrismAvaloniaDemo/.editorconfig b/e2e/Avalonia/PrismAvaloniaDemo/.editorconfig index 845700edb..e5108c99b 100644 --- a/e2e/Avalonia/PrismAvaloniaDemo/.editorconfig +++ b/e2e/Avalonia/PrismAvaloniaDemo/.editorconfig @@ -33,6 +33,7 @@ trim_trailing_whitespace = true indent_style = space indent_size = 2 trim_trailing_whitespace = true +insert_final_newline = true [*.sln] indent_size = 2 diff --git a/e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs b/e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs index 19fec496f..6dc883d12 100644 --- a/e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs +++ b/e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs @@ -1,14 +1,10 @@ -using Avalonia; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Data.Core; -using Avalonia.Data.Core.Plugins; -using Avalonia.Markup.Xaml; using Prism.DryIoc; using Prism.Ioc; using Prism.Navigation.Regions; using SampleApp.Services; using SampleApp.ViewModels; using SampleApp.Views; +using static Microsoft.IO.RecyclableMemoryStreamManager; namespace SampleApp; @@ -20,6 +16,17 @@ public override void Initialize() // Required when overriding Initialize base.Initialize(); + +#if DEBUG + // Replaces the old this.AttachDevTools(); + // NOTE: This requires connection to, http://127.0.0.1:29414/ and some IT firewalls may block it. + // Reference: https://docs.avaloniaui.net/tools/developer-tools/attaching-to-the-remote-tool + this.AttachDeveloperTools(); + ////{ + //// // Change the initialization key gesture (Default is F12) + //// options.Gesture = Avalonia.Input.KeyGesture.Parse("F11"); + ////}); +#endif } protected override AvaloniaObject CreateShell() @@ -29,13 +36,16 @@ protected override AvaloniaObject CreateShell() protected override void RegisterTypes(IContainerRegistry containerRegistry) { - // Register your Services, Views, Dialogs, etc. here - // Services containerRegistry.RegisterSingleton(); + // Views - Dialogs + containerRegistry.RegisterDialog(); + ////containerRegistry.RegisterDialogWindow(nameof(CustomDialogWindow)); + // Views - Region Navigation containerRegistry.RegisterForNavigation(); + containerRegistry.RegisterForNavigation(); containerRegistry.RegisterForNavigation(); containerRegistry.RegisterForNavigation(); } diff --git a/e2e/Avalonia/PrismAvaloniaDemo/PrismAvaloniaDemo.csproj b/e2e/Avalonia/PrismAvaloniaDemo/PrismAvaloniaDemo.csproj index 6c0c67e5d..b3943c324 100644 --- a/e2e/Avalonia/PrismAvaloniaDemo/PrismAvaloniaDemo.csproj +++ b/e2e/Avalonia/PrismAvaloniaDemo/PrismAvaloniaDemo.csproj @@ -23,8 +23,9 @@ - - + + + diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Styles/Icons.axaml b/e2e/Avalonia/PrismAvaloniaDemo/Styles/Icons.axaml index 36a5d3b89..39d720c42 100644 --- a/e2e/Avalonia/PrismAvaloniaDemo/Styles/Icons.axaml +++ b/e2e/Avalonia/PrismAvaloniaDemo/Styles/Icons.axaml @@ -1,9 +1,33 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -13,12 +37,19 @@ - https://avaloniaui.github.io/icons.html - https://docs.avaloniaui.net/tutorials/music-store-app/add-and-layout-controls - https://github.com/SKProCH/Material.Icons/blob/master/Material.Icons/MaterialIconDataProvider.PathData.cs + - https://www.svgrepo.com/ --> diff --git a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/DialogSampleViewModel.cs b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/DialogSampleViewModel.cs new file mode 100644 index 000000000..3f187112a --- /dev/null +++ b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/DialogSampleViewModel.cs @@ -0,0 +1,46 @@ +using Prism.Commands; +using Prism.Dialogs; +using SampleApp.Views; + +namespace SampleApp.ViewModels; + +public class DialogSampleViewModel : ViewModelBase +{ + private readonly IDialogService _dialog; + + private string _msgBoxTitle = string.Empty; + private string _msgBoxMessage = string.Empty; + private string _msgBoxResult = string.Empty; + + public DialogSampleViewModel(IDialogService dialog) + { + _dialog = dialog; + + MsgBoxTitle = "Sample Dialog"; + MsgBoxMessage = "Hello from the DialogSampleViewModel!"; + Title = "Dialog Sample"; + } + + public DelegateCommand CmdShowMsgBox => new(() => + { + var parameters = new DialogParameters + { + { "title", MsgBoxTitle }, + { "message", MsgBoxMessage }, + }; + + _dialog.ShowDialog(nameof(MessageBoxView), parameters, result => + { + if (result.Result == ButtonResult.OK) + MsgBoxResult = "OK"; + else if (result.Result == ButtonResult.Cancel) + MsgBoxResult = "Cancel"; + }); + }); + + public string MsgBoxMessage { get => _msgBoxMessage; set => SetProperty(ref _msgBoxMessage, value); } + + public string MsgBoxResult { get => _msgBoxResult; set => SetProperty(ref _msgBoxResult, value); } + + public string MsgBoxTitle { get => _msgBoxTitle; set => SetProperty(ref _msgBoxTitle, value); } +} diff --git a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MainWindowViewModel.cs b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MainWindowViewModel.cs index 92a7af5aa..9053bffd6 100644 --- a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MainWindowViewModel.cs +++ b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MainWindowViewModel.cs @@ -30,6 +30,11 @@ public MainWindowViewModel(IRegionManager regionManager) _regionManager.RequestNavigate(RegionNames.ContentRegion, nameof(DashboardView)); }); + public DelegateCommand CmdDialogSample => new(() => + { + _regionManager.RequestNavigate(RegionNames.ContentRegion, nameof(DialogSampleView)); + }); + public DelegateCommand CmdFlyoutMenu => new(() => { IsPaneOpened = !IsPaneOpened; diff --git a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MessageBoxViewModel.cs b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MessageBoxViewModel.cs new file mode 100644 index 000000000..1344772e2 --- /dev/null +++ b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MessageBoxViewModel.cs @@ -0,0 +1,69 @@ +using System; +using System.Text; +using Prism.Commands; +using Prism.Dialogs; +using Prism.Mvvm; + +namespace SampleApp.ViewModels; + +public class MessageBoxViewModel : BindableBase, IDialogAware +{ + private string _customMessage = string.Empty; + private int _maxHeight; + private int _maxWidth; + private string _title = "Notification"; + + public MessageBoxViewModel() + { + Title = "Alert!"; + + MaxHeight = 800; + MaxWidth = 600; + } + + public DelegateCommand CmdResult => new DelegateCommand((param) => + { + // None = 0 + // OK = 1 + // Cancel = 2 + // Abort = 3 + // Retry = 4 + // Ignore = 5 + // Yes = 6 + // No = 7 + ButtonResult result = ButtonResult.None; + + if (int.TryParse(param, out int intResult)) + result = (ButtonResult)intResult; + + RequestClose.Invoke(result); + }); + + public string CustomMessage { get => _customMessage; set => SetProperty(ref _customMessage, value); } + + public int MaxHeight { get => _maxHeight; set => SetProperty(ref _maxHeight, value); } + + public int MaxWidth { get => _maxWidth; set => SetProperty(ref _maxWidth, value); } + + public DialogCloseListener RequestClose { get; } + + public string Title { get => _title; set => SetProperty(ref _title, value); } + + /// Allows the dialog to close. + /// Return true to allow closing (i.e. OK button only). + public virtual bool CanCloseDialog() => true; + + public virtual void OnDialogClosed() + { + // Detach custom event handlers here, etc. + } + + public void OnDialogOpened(IDialogParameters parameters) + { + var title = parameters.GetValue("title"); + if (!string.IsNullOrEmpty(title)) + Title = title; + + CustomMessage = parameters.GetValue("message"); + } +} diff --git a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/SubSettingsViewModel.cs b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/SubSettingsViewModel.cs index 939bbe6cf..42ad3c865 100644 --- a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/SubSettingsViewModel.cs +++ b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/SubSettingsViewModel.cs @@ -1,3 +1,5 @@ +using System; +using System.Collections.Generic; using Prism.Commands; using Prism.Navigation.Regions; using SampleApp.Views; @@ -6,48 +8,65 @@ namespace SampleApp.ViewModels; public class SubSettingsViewModel : ViewModelBase { - private readonly IRegionManager _regionManager; - private IRegionNavigationJournal? _journal; - private string _messageNumber = string.Empty; - private string _messageText = string.Empty; - - public SubSettingsViewModel(IRegionManager regionManager) - { - _regionManager = regionManager; - - Title = "Settings - SubView"; - } - - public DelegateCommand CmdNavigateBack => new DelegateCommand(() => - { - // Go back to the previous calling page, otherwise, Dashboard. - if (_journal != null && _journal.CanGoBack) - _journal.GoBack(); - else - _regionManager.RequestNavigate(RegionNames.ContentRegion, nameof(DashboardView)); - }); - - public string MessageNumber { get => _messageNumber; set => SetProperty(ref _messageNumber, value); } - - public string MessageText { get => _messageText; set => SetProperty(ref _messageText, value); } - - /// Navigation completed successfully. - /// Navigation context. - public override void OnNavigatedTo(NavigationContext navigationContext) - { - // Used to "Go Back" to parent - _journal = navigationContext.NavigationService.Journal; - - // Display our parameters - MessageText = navigationContext.Parameters["key1"].ToString() ?? ""; - MessageNumber = navigationContext.Parameters["key2"].ToString() ?? ""; - } - - public override bool OnNavigatingTo(NavigationContext navigationContext) - { - // Navigation permission sample: - // Don't allow navigation if our keys are missing - return navigationContext.Parameters.ContainsKey("key1") && - navigationContext.Parameters.ContainsKey("key2"); - } + private readonly IRegionManager _regionManager; + private IRegionNavigationJournal? _journal; + private string _messageNumber = string.Empty; + private string _messageText = string.Empty; + + public SubSettingsViewModel(IRegionManager regionManager) + { + _regionManager = regionManager; + + Title = "Settings - SubView"; + } + + public DelegateCommand CmdNavigateBack => new DelegateCommand(() => + { + // Go back to the previous calling page, otherwise, Dashboard. + if (_journal != null && _journal.CanGoBack) + _journal.GoBack(); + else + _regionManager.RequestNavigate(RegionNames.ContentRegion, nameof(DashboardView)); + }); + + public string MessageNumber { get => _messageNumber; set => SetProperty(ref _messageNumber, value); } + + public string MessageText { get => _messageText; set => SetProperty(ref _messageText, value); } + + /// Navigation completed successfully. + /// Navigation context. + public override void OnNavigatedTo(NavigationContext navigationContext) + { + // Used to "Go Back" to parent + _journal = navigationContext.NavigationService.Journal; + + // Display our parameters + MessageText = GetKeyValueAsString(navigationContext, "key1"); + MessageNumber = GetKeyValueAsString(navigationContext, "key2"); + + } + + public override bool OnNavigatingTo(NavigationContext navigationContext) + { + // Navigation permission sample: + // Don't allow navigation if our keys are missing + return navigationContext.Parameters.ContainsKey("key1") && + navigationContext.Parameters.ContainsKey("key2"); + } + + public static string GetKeyValueAsString(NavigationContext context, string targetKey, string defaultValue = "") + { + var searchList = context.Parameters; + if (searchList == null || targetKey == null) + return defaultValue; + + foreach (KeyValuePair kvp in searchList) + { + // Safe string comparison (Ordinal ignores regional culture bugs) + if (string.Equals(kvp.Key, targetKey, StringComparison.Ordinal)) + return kvp.Value?.ToString() ?? defaultValue; + } + + return defaultValue; + } } diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml b/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml index d9b8271ee..6979051a0 100644 --- a/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml +++ b/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml @@ -8,7 +8,9 @@ x:Class="SampleApp.Views.DashboardView" x:CompileBindings="True" x:DataType="vm:DashboardViewModel" - d:DesignHeight="350" d:DesignWidth="500" mc:Ignorable="d"> + d:DesignHeight="350" + d:DesignWidth="500" + mc:Ignorable="d"> + + + + + + + + + + + +