From d3bb492a886f5a1906ecd524848677eb22a13492 Mon Sep 17 00:00:00 2001 From: Damian Suess Date: Tue, 9 Jun 2026 09:14:32 -0400 Subject: [PATCH 1/8] Upgraded to latest Avalonia packages v12.0.4 and repointed Diagnostics support https://docs.avaloniaui.net/docs/avalonia12-breaking-changes --- Directory.Packages.props | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index e913b828d..2bc107ecc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -61,14 +61,14 @@ - - - - - - - - + + + + + + + + From 8cf354fc43cfceb8022f7648e738714403e5ded6 Mon Sep 17 00:00:00 2001 From: Damian Suess Date: Sat, 1 Aug 2026 09:33:33 -0400 Subject: [PATCH 2/8] bump to latest --- Directory.Packages.props | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 2bc107ecc..3fde8c6c3 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -61,14 +61,14 @@ - - + + - - - - - + + + + + From ec4041acac8d20db040d424e773b438acb420247 Mon Sep 17 00:00:00 2001 From: Damian Suess Date: Sat, 5 Sep 2026 10:25:45 -0400 Subject: [PATCH 3/8] Removed all warnings from Avalonia e2e demo app, handling potential missing navigation parameters. And updated to new Diagnostics NuGet pkg reference. --- .../PrismAvaloniaDemo.csproj | 5 +- .../ViewModels/SubSettingsViewModel.cs | 107 +++++++++++------- .../Views/DashboardView.axaml.cs | 2 +- 3 files changed, 67 insertions(+), 47 deletions(-) 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/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.cs b/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml.cs index a7fa3dd6a..71ea3481a 100644 --- a/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml.cs +++ b/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml.cs @@ -19,6 +19,6 @@ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) // Initialize the WindowNotificationManager with the "TopLevel". Previously (v0.10), MainWindow var notifyService = ContainerLocator.Current.Resolve(); - notifyService.SetHostWindow(TopLevel.GetTopLevel(this)); + notifyService.SetHostWindow(TopLevel.GetTopLevel(this)!); } } From 623e5e2a79542b0c107c65fae1598550a449d298 Mon Sep 17 00:00:00 2001 From: Damian Suess Date: Sat, 5 Sep 2026 11:32:23 -0400 Subject: [PATCH 4/8] Prism.Avalonia DialogWindow no longer a compiled binding as the parent is unknown until it is used --- src/Avalonia/Prism.Avalonia/Dialogs/DialogWindow.axaml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Avalonia/Prism.Avalonia/Dialogs/DialogWindow.axaml b/src/Avalonia/Prism.Avalonia/Dialogs/DialogWindow.axaml index ee77baa2d..fc5cd4097 100644 --- a/src/Avalonia/Prism.Avalonia/Dialogs/DialogWindow.axaml +++ b/src/Avalonia/Prism.Avalonia/Dialogs/DialogWindow.axaml @@ -3,6 +3,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Class="Prism.Dialogs.DialogWindow" + x:CompileBindings="False" Title="{Binding Title}" WindowStartupLocation="CenterOwner"> From 095857f42b71a8ed69699d570cc88df7e1ef57e6 Mon Sep 17 00:00:00 2001 From: Damian Suess Date: Sat, 5 Sep 2026 13:53:05 -0400 Subject: [PATCH 5/8] Prism.Avalonia - Added simple Dialog registration example to end-to-end project. Added Styles icons preview example. Bumped tabs to 4 --- e2e/Avalonia/PrismAvaloniaDemo/.editorconfig | 1 + e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs | 12 ++-- .../PrismAvaloniaDemo/Styles/Icons.axaml | 46 +++++++++---- .../ViewModels/DialogSampleViewModel.cs | 46 +++++++++++++ .../ViewModels/MainWindowViewModel.cs | 5 ++ .../ViewModels/MessageBoxViewModel.cs | 69 +++++++++++++++++++ .../Views/DashboardView.axaml | 24 ++++--- .../Views/DashboardView.axaml.cs | 22 +++--- .../Views/DialogSampleView.axaml | 50 ++++++++++++++ .../Views/DialogSampleView.axaml.cs | 13 ++++ .../PrismAvaloniaDemo/Views/MainWindow.axaml | 11 ++- .../Views/MessageBoxView.axaml | 67 ++++++++++++++++++ .../Views/MessageBoxView.axaml.cs | 19 +++++ .../Views/SubSettingsView.axaml.cs | 8 +-- 14 files changed, 348 insertions(+), 45 deletions(-) create mode 100644 e2e/Avalonia/PrismAvaloniaDemo/ViewModels/DialogSampleViewModel.cs create mode 100644 e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MessageBoxViewModel.cs create mode 100644 e2e/Avalonia/PrismAvaloniaDemo/Views/DialogSampleView.axaml create mode 100644 e2e/Avalonia/PrismAvaloniaDemo/Views/DialogSampleView.axaml.cs create mode 100644 e2e/Avalonia/PrismAvaloniaDemo/Views/MessageBoxView.axaml create mode 100644 e2e/Avalonia/PrismAvaloniaDemo/Views/MessageBoxView.axaml.cs 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..12720e4bb 100644 --- a/e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs +++ b/e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs @@ -1,8 +1,3 @@ -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; @@ -29,13 +24,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/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/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"> + + + + + + + + + + + +