diff --git a/e2e/Avalonia/PrismAvaloniaDemo/App.axaml b/e2e/Avalonia/PrismAvaloniaDemo/App.axaml
index 3dca8cf60..136cd24b1 100644
--- a/e2e/Avalonia/PrismAvaloniaDemo/App.axaml
+++ b/e2e/Avalonia/PrismAvaloniaDemo/App.axaml
@@ -1,11 +1,13 @@
+
+
+
\ No newline at end of file
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs b/e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs
index cad82d3a7..19fec496f 100644
--- a/e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs
+++ b/e2e/Avalonia/PrismAvaloniaDemo/App.axaml.cs
@@ -5,6 +5,8 @@
using Avalonia.Markup.Xaml;
using Prism.DryIoc;
using Prism.Ioc;
+using Prism.Navigation.Regions;
+using SampleApp.Services;
using SampleApp.ViewModels;
using SampleApp.Views;
@@ -27,6 +29,26 @@ protected override AvaloniaObject CreateShell()
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
- // Register you Services, Views, Dialogs, etc.
+ // Register your Services, Views, Dialogs, etc. here
+
+ // Services
+ containerRegistry.RegisterSingleton();
+
+ // Views - Region Navigation
+ containerRegistry.RegisterForNavigation();
+ containerRegistry.RegisterForNavigation();
+ containerRegistry.RegisterForNavigation();
+ }
+
+ /// Called after Initialize.
+ protected override void OnInitialized()
+ {
+ // Register Views to the Region it will appear in. Don't register them in the ViewModel.
+ var regionManager = Container.Resolve();
+
+ // WARNING: Prism v11.0.0
+ // - DataTemplates MUST define a DataType or else an XAML error will be thrown
+ // - Error: DataTemplate inside of DataTemplates must have a DataType set
+ regionManager.RegisterViewWithRegion(RegionNames.ContentRegion, typeof(DashboardView));
}
}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/PrismAvaloniaDemo.csproj b/e2e/Avalonia/PrismAvaloniaDemo/PrismAvaloniaDemo.csproj
index f6a1629e2..81b1e5c48 100644
--- a/e2e/Avalonia/PrismAvaloniaDemo/PrismAvaloniaDemo.csproj
+++ b/e2e/Avalonia/PrismAvaloniaDemo/PrismAvaloniaDemo.csproj
@@ -2,6 +2,7 @@
WinExe
net8.0
+ latest
enable
true
app.manifest
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/RegionNames.cs b/e2e/Avalonia/PrismAvaloniaDemo/RegionNames.cs
new file mode 100644
index 000000000..7ebaa5ddd
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/RegionNames.cs
@@ -0,0 +1,8 @@
+namespace SampleApp;
+
+public static class RegionNames
+{
+ public const string ContentRegion = "ContentRegion";
+ public const string FooterRegion = "FooterRegion";
+ public const string SidebarRegion = "SidebarRegion";
+}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Services/INotificationService.cs b/e2e/Avalonia/PrismAvaloniaDemo/Services/INotificationService.cs
new file mode 100644
index 000000000..f3f7d5f52
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/Services/INotificationService.cs
@@ -0,0 +1,13 @@
+using System;
+using Avalonia.Controls;
+
+namespace SampleApp.Services;
+
+public interface INotificationService
+{
+ int NotificationTimeout { get; set; }
+
+ void SetHostWindow(TopLevel window);
+
+ void Show(string title, string message, Action? onClick = null);
+}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Services/NotificationService.cs b/e2e/Avalonia/PrismAvaloniaDemo/Services/NotificationService.cs
new file mode 100644
index 000000000..5258fca09
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/Services/NotificationService.cs
@@ -0,0 +1,43 @@
+using Avalonia.Controls.Notifications;
+
+namespace SampleApp.Services;
+
+public class NotificationService : INotificationService
+{
+ private WindowNotificationManager? _notificationManager;
+ private int _notificationTimeout = 10;
+
+ public int NotificationTimeout { get => _notificationTimeout; set => _notificationTimeout = (value < 0) ? 0 : value; }
+
+ /// Set the host window.
+ /// Parent window.
+ public void SetHostWindow(TopLevel hostWindow)
+ {
+ var notificationManager = new WindowNotificationManager(hostWindow)
+ {
+ Position = NotificationPosition.BottomRight,
+ MaxItems = 4,
+ Margin = new Thickness(0, 0, 15, 40)
+ };
+
+ _notificationManager = notificationManager;
+ }
+
+ /// Display the notification.
+ /// Title.
+ /// Message.
+ /// Optional OnClick action.
+ public void Show(string title, string message, Action? onClick = null)
+ {
+ if (_notificationManager is { } nm)
+ {
+ nm.Show(
+ new Notification(
+ title,
+ message,
+ NotificationType.Information,
+ TimeSpan.FromSeconds(_notificationTimeout),
+ onClick));
+ }
+ }
+}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Styles/Icons.axaml b/e2e/Avalonia/PrismAvaloniaDemo/Styles/Icons.axaml
new file mode 100644
index 000000000..36a5d3b89
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/Styles/Icons.axaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/DashboardViewModel.cs b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/DashboardViewModel.cs
new file mode 100644
index 000000000..b9ae3ad21
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/DashboardViewModel.cs
@@ -0,0 +1,85 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Avalonia;
+using Avalonia.Styling;
+using Prism.Commands;
+using SampleApp.Services;
+
+namespace SampleApp.ViewModels;
+
+public class DashboardViewModel : ViewModelBase
+{
+ private readonly INotificationService _notification;
+ private int _counter = 0;
+ private ObservableCollection _listItems = new();
+ private int _listItemSelected = -1;
+ private string _listItemText = string.Empty;
+ private ThemeVariant? _themeSelected;
+
+ public DashboardViewModel(INotificationService notifyService)
+ {
+ _notification = notifyService;
+
+ ThemeSelected = Application.Current!.RequestedThemeVariant;
+ }
+
+ public DelegateCommand CmdAddItem => new(() =>
+ {
+ _counter++;
+ ListItems.Add($"Item Number: {_counter}");
+
+ // Optionally use, `Insert(0, ..)` to insert items at the top
+ //ListItems.Insert(0, entry);
+ });
+
+ public DelegateCommand CmdClearItems => new(() =>
+ {
+ ListItems.Clear();
+ });
+
+ public DelegateCommand CmdNotification => new(() =>
+ {
+ _notification.Show("Hello Prism!", "Notification Pop-up Message.");
+
+ // Alternate OnClick action
+ ////_notification.Show("Hello Prism!", "Notification Pop-up Message.", () =>
+ ////{
+ //// // Action to perform
+ ////});
+ });
+
+ public ObservableCollection ListItems { get => _listItems; set => SetProperty(ref _listItems, value); }
+
+ public int ListItemSelected
+ {
+ get => _listItemSelected;
+ set
+ {
+ SetProperty(ref _listItemSelected, value);
+
+ if (value == -1)
+ return;
+
+ ListItemText = ListItems[ListItemSelected];
+ }
+ }
+
+ public string ListItemText { get => _listItemText; set => SetProperty(ref _listItemText, value); }
+
+ public ThemeVariant? ThemeSelected
+ {
+ get => _themeSelected;
+ set
+ {
+ SetProperty(ref _themeSelected, value);
+ Application.Current!.RequestedThemeVariant = _themeSelected;
+ }
+ }
+
+ public List ThemeStyles => new()
+ {
+ ThemeVariant.Default,
+ ThemeVariant.Dark,
+ ThemeVariant.Light,
+ };
+}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MainWindowViewModel.cs b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MainWindowViewModel.cs
index 4efdc1b73..203da5bf7 100644
--- a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MainWindowViewModel.cs
+++ b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/MainWindowViewModel.cs
@@ -1,13 +1,41 @@
+using Prism.Commands;
+using Prism.Navigation.Regions;
+
+using SampleApp.Views;
+
namespace SampleApp.ViewModels;
public class MainWindowViewModel : ViewModelBase
{
- public MainWindowViewModel()
+ private readonly IRegionManager _regionManager;
+ private bool _isPaneOpened;
+
+ public MainWindowViewModel(IRegionManager regionManager)
{
- Title = "Welcome to Prism.Avalonia!";
+ // Since this is a basic ShellWindow, there's not much to do here.
+ // For enterprise apps, you could register up subscriptions
+ // or other startup background tasks so that they get triggered
+ // on startup, rather than putting them in the DashboardViewModel.
+ //
+ // For example, initiate the pulling of News Feeds, etc.
+
+ _regionManager = regionManager;
+ Title = "Sample Prism.Avalonia SplitView!";
+ IsPaneOpened = true;
}
-#pragma warning disable CA1822 // Mark members as static
- public string Greeting => "Hello from, Prism.Avalonia!";
-#pragma warning restore CA1822 // Mark members as static
+ public DelegateCommand CmdDashboard => new(() =>
+ {
+ // _journal.Clear();
+ _regionManager.RequestNavigate(RegionNames.ContentRegion, nameof(DashboardView));
+ });
+
+ public DelegateCommand CmdFlyoutMenu => new(() =>
+ {
+ IsPaneOpened = !IsPaneOpened;
+ });
+
+ public DelegateCommand CmdSettings => new(() => _regionManager.RequestNavigate(RegionNames.ContentRegion, nameof(SettingsView)));
+
+ public bool IsPaneOpened { get => _isPaneOpened; set => SetProperty(ref _isPaneOpened, value); }
}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/SettingsViewModel.cs b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/SettingsViewModel.cs
new file mode 100644
index 000000000..4ede0fe9a
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/SettingsViewModel.cs
@@ -0,0 +1,35 @@
+using SampleApp.Views;
+using Prism.Commands;
+using Prism.Navigation;
+using Prism.Navigation.Regions;
+
+namespace SampleApp.ViewModels
+{
+ public class SettingsViewModel : ViewModelBase
+ {
+ private readonly IRegionManager _regionManager;
+
+ public SettingsViewModel(IRegionManager regionManager)
+ {
+ _regionManager = regionManager;
+ Title = "Settings";
+ }
+
+ public DelegateCommand CmdNavigateToChild => new DelegateCommand(() =>
+ {
+ var navParams = new NavigationParameters();
+ navParams.Add("key1", "Some text");
+ navParams.Add("key2", 999);
+
+ _regionManager.RequestNavigate(
+ RegionNames.ContentRegion,
+ nameof(SubSettingsView),
+ navParams);
+ });
+
+ public override void OnNavigatedFrom(NavigationContext navigationContext)
+ {
+ base.OnNavigatedFrom(navigationContext);
+ }
+ }
+}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/SubSettingsViewModel.cs b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/SubSettingsViewModel.cs
new file mode 100644
index 000000000..939bbe6cf
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/SubSettingsViewModel.cs
@@ -0,0 +1,53 @@
+using Prism.Commands;
+using Prism.Navigation.Regions;
+using SampleApp.Views;
+
+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");
+ }
+}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/ViewModelBase.cs b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/ViewModelBase.cs
index 229084d99..048a65f40 100644
--- a/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/ViewModelBase.cs
+++ b/e2e/Avalonia/PrismAvaloniaDemo/ViewModels/ViewModelBase.cs
@@ -1,11 +1,45 @@
using Prism.Mvvm;
+using Prism.Navigation.Regions;
namespace SampleApp.ViewModels;
-public class ViewModelBase : BindableBase
+public class ViewModelBase : BindableBase, INavigationAware
{
private string _title = string.Empty;
- /// Gets or sets the title of the view.
+ /// Gets or sets the title of the View.
public string Title { get => _title; set => SetProperty(ref _title, value); }
+
+ ///
+ /// Called to determine if this instance can handle the navigation request.
+ /// Don't call this directly, use .
+ ///
+ /// The navigation context.
+ /// if this instance accepts the navigation request; otherwise, .
+ public virtual bool IsNavigationTarget(NavigationContext navigationContext)
+ {
+ // Auto-allow navigation
+ return OnNavigatingTo(navigationContext);
+ }
+
+ /// Called when the implementer is being navigated away from.
+ /// The navigation context.
+ public virtual void OnNavigatedFrom(NavigationContext navigationContext)
+ {
+ }
+
+ /// Called when the implementer has been navigated to.
+ /// The navigation context.
+ public virtual void OnNavigatedTo(NavigationContext navigationContext)
+ {
+ }
+
+ /// Navigation validation checker.
+ /// Override for Prism 7.2's IsNavigationTarget.
+ /// The navigation context.
+ /// if this instance accepts the navigation request; otherwise, .
+ public virtual bool OnNavigatingTo(NavigationContext navigationContext)
+ {
+ return true;
+ }
}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml b/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml
new file mode 100644
index 000000000..d9b8271ee
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml.cs b/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml.cs
new file mode 100644
index 000000000..a7fa3dd6a
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/Views/DashboardView.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia;
+using Avalonia.Controls;
+using Prism.Ioc;
+using SampleApp.Services;
+
+namespace SampleApp.Views;
+
+/// DashboardView.
+public partial class DashboardView : UserControl
+{
+ public DashboardView()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+
+ // Initialize the WindowNotificationManager with the "TopLevel". Previously (v0.10), MainWindow
+ var notifyService = ContainerLocator.Current.Resolve();
+ notifyService.SetHostWindow(TopLevel.GetTopLevel(this));
+ }
+}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Views/MainWindow.axaml b/e2e/Avalonia/PrismAvaloniaDemo/Views/MainWindow.axaml
index 651f1a0e4..c4196afc7 100644
--- a/e2e/Avalonia/PrismAvaloniaDemo/Views/MainWindow.axaml
+++ b/e2e/Avalonia/PrismAvaloniaDemo/Views/MainWindow.axaml
@@ -1,17 +1,111 @@
+ Width="700"
+ Height="400"
+ Background="Transparent"
+ TransparencyLevelHint="AcrylicBlur">
+
+
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Views/SettingsView.axaml b/e2e/Avalonia/PrismAvaloniaDemo/Views/SettingsView.axaml
new file mode 100644
index 000000000..b699c9bbf
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/Views/SettingsView.axaml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Views/SettingsView.axaml.cs b/e2e/Avalonia/PrismAvaloniaDemo/Views/SettingsView.axaml.cs
new file mode 100644
index 000000000..1e09aeaf2
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/Views/SettingsView.axaml.cs
@@ -0,0 +1,12 @@
+using Avalonia.Controls;
+
+namespace SampleApp.Views;
+
+/// Sample Settings View.
+public partial class SettingsView : UserControl
+{
+ public SettingsView()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Views/SubSettingsView.axaml b/e2e/Avalonia/PrismAvaloniaDemo/Views/SubSettingsView.axaml
new file mode 100644
index 000000000..8956b11d6
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/Views/SubSettingsView.axaml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/e2e/Avalonia/PrismAvaloniaDemo/Views/SubSettingsView.axaml.cs b/e2e/Avalonia/PrismAvaloniaDemo/Views/SubSettingsView.axaml.cs
new file mode 100644
index 000000000..aa5c7558d
--- /dev/null
+++ b/e2e/Avalonia/PrismAvaloniaDemo/Views/SubSettingsView.axaml.cs
@@ -0,0 +1,11 @@
+using Avalonia.Controls;
+
+namespace SampleApp.Views;
+
+public partial class SubSettingsView : UserControl
+{
+ public SubSettingsView()
+ {
+ InitializeComponent();
+ }
+}