diff --git a/Source/Collections/AsyncVirtualObservableReadOnlyList.cs b/Source/Collections/AsyncVirtualObservableReadOnlyList.cs
index cc4781e..2871bdd 100644
--- a/Source/Collections/AsyncVirtualObservableReadOnlyList.cs
+++ b/Source/Collections/AsyncVirtualObservableReadOnlyList.cs
@@ -289,7 +289,19 @@ namespace Nuclex.Avalonia.Collections {
/// Item whose index will be determined
/// The index of the item in the list or -1 if not found
public int IndexOf(TItem item) {
- return this.typedList.IndexOf(item);
+ requireCount();
+ requireAllPages();
+
+ // TODO: this won't work, it will compare the placeholder items :-/
+
+ IComparer itemComparer = Comparer.Default;
+ for(int index = 0; index < this.assumedCount.Value; ++index) {
+ if(itemComparer.Compare(this.typedList[index], item) == 0) {
+ return index;
+ }
+ }
+
+ return -1;
}
/// Inserts an item into the list at the specified index
@@ -344,10 +356,8 @@ namespace Nuclex.Avalonia.Collections {
/// Item the list will be checked for
/// True if the list contains the specified items
public bool Contains(TItem item) {
- requireCount();
- requireAllPages();
-
- return this.typedList.Contains(item);
+ // TODO: this won't work, it will compare the placeholder items :-/
+ return (IndexOf(item) != -1);
}
/// Copies the contents of the list into an array
@@ -359,14 +369,13 @@ namespace Nuclex.Avalonia.Collections {
requireCount();
requireAllPages();
+ // TODO: this won't work, it will copy the placeholder items :-/
this.typedList.CopyTo(array, arrayIndex);
}
/// Total number of items in the list
public int Count {
- get {
- return requireCount();
- }
+ get { return requireCount(); }
}
/// Whether the list is a read-only list
diff --git a/Source/IActiveWindowTracker.cs b/Source/IActiveWindowTracker.cs
index 82d341c..ecb899d 100644
--- a/Source/IActiveWindowTracker.cs
+++ b/Source/IActiveWindowTracker.cs
@@ -1,35 +1,35 @@
-#region Apache License 2.0
-/*
-Nuclex Foundation libraries for .NET
-Copyright (C) 2002-2025 Markus Ewald / Nuclex Development Labs
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-#endregion // Apache License 2.0
-
-using System;
-
-using Avalonia.Controls;
-
-namespace Nuclex.Avalonia {
-
- /// Allows the currently active top level window to be looked up
- public interface IActiveWindowTracker {
-
- /// The currently active top-level or modal window
- Window? ActiveWindow { get; }
-
- }
-
-} // namespace Nuclex.Avalonia
-
+#region Apache License 2.0
+/*
+Nuclex Foundation libraries for .NET
+Copyright (C) 2002-2025 Markus Ewald / Nuclex Development Labs
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#endregion // Apache License 2.0
+
+using System;
+
+using Avalonia.Controls;
+
+namespace Nuclex.Avalonia {
+
+ /// Allows the currently active top level window to be looked up
+ public interface IActiveWindowTracker {
+
+ /// The currently active top-level or modal window
+ Window? ActiveWindow { get; }
+
+ }
+
+} // namespace Nuclex.Avalonia
+
diff --git a/Source/IWindowManager.cs b/Source/IWindowManager.cs
index e050f52..d68ed93 100644
--- a/Source/IWindowManager.cs
+++ b/Source/IWindowManager.cs
@@ -1,114 +1,114 @@
-#region Apache License 2.0
-/*
-Nuclex Foundation libraries for .NET
-Copyright (C) 2002-2025 Markus Ewald / Nuclex Development Labs
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-#endregion // Apache License 2.0
-
-using System;
-using System.Threading.Tasks;
-
-using Avalonia.Controls;
-
-namespace Nuclex.Avalonia {
-
- /// Manages open windows and connecting them to view models
- public interface IWindowManager : IActiveWindowTracker {
-
- /// Opens a view as a new root window of the application
- ///
- /// Type of view model a root window will be opened for
- ///
- ///
- /// View model a window will be opened for. If null, the view model will be
- /// created as well (unless the dialog already specifies one as a resource)
- ///
- ///
- /// Whether the view model should be disposed when the view is closed
- ///
- /// The window that has been opened by the window manager
- Window OpenRoot(
- TViewModel? viewModel = null, bool disposeOnClose = true
- ) where TViewModel : class;
-
- /// Displays a view as a modal window
- ///
- /// Type of the view model for which a view will be displayed
- ///
- ///
- /// View model a modal window will be displayed for. If null, the view model will
- /// be created as well (unless the dialog already specifies one as a resource)
- ///
- ///
- /// Whether the view model should be disposed when the view is closed
- ///
- /// The return value of the modal window
- Task ShowModalAsync(
- TViewModel? viewModel = null, bool disposeOnClose = false
- ) where TViewModel : class;
-
- /// Displays a view as a modal window
- ///
- /// Type of result the modal dialog will return to the caller
- ///
- ///
- /// Type of the view model for which a view will be displayed
- ///
- ///
- /// View model a modal window will be displayed for. If null, the view model will
- /// be created as well (unless the dialog already specifies one as a resource)
- ///
- ///
- /// Whether the view model should be disposed when the view is closed
- ///
- /// The return value of the modal window
- Task ShowModalAsync(
- TViewModel? viewModel = null, bool disposeOnClose = true
- ) where TViewModel : class;
-
- /// Creates the view for the specified view model
- ///
- /// Type of view model for which a view will be created
- ///
- ///
- /// View model a view will be created for. If null, the view model will be
- /// created as well (unless the dialog already specifies one as a resource)
- ///
- /// The view for the specified view model
- Control CreateView(TViewModel? viewModel = null)
- where TViewModel : class;
-
- /// Creates a view model without a matching view
- /// Type of view model that will be created
- /// The new view model
- ///
- ///
- /// This is useful if a view model needs to create child view models (i.e. paged container
- /// and wants to ensure the same dependency injector (if any) if used as the window
- /// manager uses for other view models it creates.
- ///
- ///
- /// This way, view models can set up their child view models without having to immediately
- /// bind a view to them. Later on, views can use the window manager to create a matching
- /// child view and store it in a container.
- ///
- ///
- TViewModel CreateViewModel()
- where TViewModel : class;
-
- }
-
-} // namespace Nuclex.Avalonia
-
+#region Apache License 2.0
+/*
+Nuclex Foundation libraries for .NET
+Copyright (C) 2002-2025 Markus Ewald / Nuclex Development Labs
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#endregion // Apache License 2.0
+
+using System;
+using System.Threading.Tasks;
+
+using Avalonia.Controls;
+
+namespace Nuclex.Avalonia {
+
+ /// Manages open windows and connecting them to view models
+ public interface IWindowManager : IActiveWindowTracker {
+
+ /// Opens a view as a new root window of the application
+ ///
+ /// Type of view model a root window will be opened for
+ ///
+ ///
+ /// View model a window will be opened for. If null, the view model will be
+ /// created as well (unless the dialog already specifies one as a resource)
+ ///
+ ///
+ /// Whether the view model should be disposed when the view is closed
+ ///
+ /// The window that has been opened by the window manager
+ Window OpenRoot(
+ TViewModel? viewModel = null, bool disposeOnClose = true
+ ) where TViewModel : class;
+
+ /// Displays a view as a modal window
+ ///
+ /// Type of the view model for which a view will be displayed
+ ///
+ ///
+ /// View model a modal window will be displayed for. If null, the view model will
+ /// be created as well (unless the dialog already specifies one as a resource)
+ ///
+ ///
+ /// Whether the view model should be disposed when the view is closed
+ ///
+ /// The return value of the modal window
+ Task ShowModalAsync(
+ TViewModel? viewModel = null, bool disposeOnClose = false
+ ) where TViewModel : class;
+
+ /// Displays a view as a modal window
+ ///
+ /// Type of result the modal dialog will return to the caller
+ ///
+ ///
+ /// Type of the view model for which a view will be displayed
+ ///
+ ///
+ /// View model a modal window will be displayed for. If null, the view model will
+ /// be created as well (unless the dialog already specifies one as a resource)
+ ///
+ ///
+ /// Whether the view model should be disposed when the view is closed
+ ///
+ /// The return value of the modal window
+ Task ShowModalAsync(
+ TViewModel? viewModel = null, bool disposeOnClose = true
+ ) where TViewModel : class;
+
+ /// Creates the view for the specified view model
+ ///
+ /// Type of view model for which a view will be created
+ ///
+ ///
+ /// View model a view will be created for. If null, the view model will be
+ /// created as well (unless the dialog already specifies one as a resource)
+ ///
+ /// The view for the specified view model
+ Control CreateView(TViewModel? viewModel = null)
+ where TViewModel : class;
+
+ /// Creates a view model without a matching view
+ /// Type of view model that will be created
+ /// The new view model
+ ///
+ ///
+ /// This is useful if a view model needs to create child view models (i.e. paged container
+ /// and wants to ensure the same dependency injector (if any) if used as the window
+ /// manager uses for other view models it creates.
+ ///
+ ///
+ /// This way, view models can set up their child view models without having to immediately
+ /// bind a view to them. Later on, views can use the window manager to create a matching
+ /// child view and store it in a container.
+ ///
+ ///
+ TViewModel CreateViewModel()
+ where TViewModel : class;
+
+ }
+
+} // namespace Nuclex.Avalonia
+
diff --git a/Source/Messages/AvaloniaMessagePresenter.cs b/Source/Messages/AvaloniaMessagePresenter.cs
index e7c181b..af5345b 100644
--- a/Source/Messages/AvaloniaMessagePresenter.cs
+++ b/Source/Messages/AvaloniaMessagePresenter.cs
@@ -1,188 +1,188 @@
-#region Apache License 2.0
-/*
-Nuclex Foundation libraries for .NET
-Copyright (C) 2002-2025 Markus Ewald / Nuclex Development Labs
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-#endregion // Apache License 2.0
-
-using System;
-using System.Threading.Tasks;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
-#if NET6_0_OR_GREATER
-using System.Runtime.Versioning;
-#endif
-
-using Avalonia.Controls;
-
-using MessageBoxIcon = MsBox.Avalonia.Enums.Icon;
-using MessageBoxButtons = MsBox.Avalonia.Enums.ButtonEnum;
-using MessageDialogResult = MsBox.Avalonia.Enums.ButtonResult;
-
-namespace Nuclex.Avalonia.Messages {
-
- /// Uses Avalonia to display message boxes
- public class AvaloniaMessagePresenter : IMessageService {
-
- #region class MessageScope
-
- /// Triggers the message displayed and acknowledged events
- private class MessageScope : IDisposable {
-
- ///
- /// Initializes a new message scope, triggering the message displayed event
- ///
- /// Message service the scope belongs to
- /// Image of the message being displayed
- /// Text contained in the message being displayed
- public MessageScope(
- AvaloniaMessagePresenter self, MessageBoxIcon image, MessageText text
- ) {
- EventHandler? messageDisplayed = self.MessageDisplaying;
- if(messageDisplayed != null) {
- messageDisplayed(this, new MessageEventArgs(image, text));
- }
-
- this.self = self;
- }
-
- /// Triggers the message acknowledged event
- public void Dispose() {
- EventHandler? messageAcknowledged = self.MessageAcknowledged;
- if(messageAcknowledged != null) {
- messageAcknowledged(this, EventArgs.Empty);
- }
- }
-
- /// Message service the scope belongs to
- private AvaloniaMessagePresenter self;
-
- }
-
- #endregion // class MessageScope
-
- /// Triggered when a message is displayed to the user
- public event EventHandler? MessageDisplaying;
-
- /// Triggered when the user has acknowledged the current message
- public event EventHandler? MessageAcknowledged;
-
- /// Initializes a new Avalonia message service
- /// Used to determine the current top-level window
- public AvaloniaMessagePresenter(IActiveWindowTracker tracker) {
- this.tracker = tracker;
- }
-
- /// Asks the user a question that can be answered via several buttons
- /// Image that will be shown on the message box
- /// Text that will be shown to the user
- /// Buttons available for the user to click on
- /// The button the user has clicked on
- public Task ShowQuestionAsync(
- MessageBoxIcon image, MessageText text, MessageBoxButtons buttons
- ) {
- using(var scope = new MessageScope(this, image, text)) {
- MsBox.Avalonia.Base.IMsBox messageBox = (
- MsBox.Avalonia.MessageBoxManager.GetMessageBoxStandard(
- new MsBox.Avalonia.Dto.MessageBoxStandardParams() {
- ContentTitle = text.Caption,
- ContentHeader = text.Message,
- ContentMessage = text.Details ?? string.Empty,
- ButtonDefinitions = buttons,
- Icon = image,
- WindowStartupLocation = WindowStartupLocation.CenterOwner
- }
- )
- );
- return messageBox.ShowAsync(); // TODO: Make modal to current or main window
- }
- }
-
- /// Displays a notification to the user
- /// Image that will be shown on the message bx
- /// Text that will be shown to the user
- public Task ShowNotificationAsync(MessageBoxIcon image, MessageText text) {
- using(var scope = new MessageScope(this, image, text)) {
- MsBox.Avalonia.Base.IMsBox messageBox = (
- MsBox.Avalonia.MessageBoxManager.GetMessageBoxStandard(
- new MsBox.Avalonia.Dto.MessageBoxStandardParams() {
- ContentTitle = text.Caption,
- ContentHeader = text.Message,
- ContentMessage = text.Details ?? string.Empty,
- ButtonDefinitions = MessageBoxButtons.Ok,
- Icon = image,
- WindowStartupLocation = WindowStartupLocation.CenterOwner
- }
- )
- );
-
- Window? activeWindow = this.tracker.ActiveWindow;
- if(activeWindow == null) {
- return messageBox.ShowAsync();
- } else {
- //return messageBox.ShowAsPopupAsync(activeWindow);
- return messageBox.ShowWindowDialogAsync(activeWindow);
- }
- }
- }
-
- /// Reports an error using the system's message box functions
- /// Title of the message box
- /// Message text that will be displayed
- public static void FallbackReportError(string title, string message) {
- // TODO: Escape quotes for the command-line tools
- // TODO: Wait for the child process to exit so display is certain
-
- if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
- MessageBoxW(IntPtr.Zero, message, title, MB_OK | MB_ICONEXCLAMATION);
- } else if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
- Process.Start("zenity", $"--error --title=\"{title}\" --text=\"{message}\"");
- } else if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
- Process.Start("osascript", $"-e 'display dialog \"{message}\" with title \"{title}\" with icon stop'");
- }
- }
-
- /// Windows only: display a message box with an OK button
-#if NET6_0_OR_GREATER
- [SupportedOSPlatform("windows")]
-#endif
- private const uint MB_OK = 0x00000000;
-
- /// Windows only: display a message box with an Exclamation icon
-#if NET6_0_OR_GREATER
- [SupportedOSPlatform("windows")]
-#endif
- private const uint MB_ICONEXCLAMATION = 0x00000030;
-
- /// Windows only: displays a native Windows message box
- /// Handle of the window that owns the message box
- /// Text that should be in the message box
- /// Caption or window title of the message box
- /// Which icons and buttons that message box should have
- /// How the user closed the message box and which button they clicked
- [DllImport("user32.dll", CharSet = CharSet.Unicode)]
-#if NET6_0_OR_GREATER
- [SupportedOSPlatform("windows")]
-#endif
- private static extern int MessageBoxW(IntPtr parentWindowHandle, string text, string caption, uint type);
-
- // Provides the currently active top-level window
- private IActiveWindowTracker tracker;
-
- }
-
-} // namespace Nuclex.Avalonia.Messages
-
+#region Apache License 2.0
+/*
+Nuclex Foundation libraries for .NET
+Copyright (C) 2002-2025 Markus Ewald / Nuclex Development Labs
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#endregion // Apache License 2.0
+
+using System;
+using System.Threading.Tasks;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+#if NET6_0_OR_GREATER
+using System.Runtime.Versioning;
+#endif
+
+using Avalonia.Controls;
+
+using MessageBoxIcon = MsBox.Avalonia.Enums.Icon;
+using MessageBoxButtons = MsBox.Avalonia.Enums.ButtonEnum;
+using MessageDialogResult = MsBox.Avalonia.Enums.ButtonResult;
+
+namespace Nuclex.Avalonia.Messages {
+
+ /// Uses Avalonia to display message boxes
+ public class AvaloniaMessagePresenter : IMessageService {
+
+ #region class MessageScope
+
+ /// Triggers the message displayed and acknowledged events
+ private class MessageScope : IDisposable {
+
+ ///
+ /// Initializes a new message scope, triggering the message displayed event
+ ///
+ /// Message service the scope belongs to
+ /// Image of the message being displayed
+ /// Text contained in the message being displayed
+ public MessageScope(
+ AvaloniaMessagePresenter self, MessageBoxIcon image, MessageText text
+ ) {
+ EventHandler? messageDisplayed = self.MessageDisplaying;
+ if(messageDisplayed != null) {
+ messageDisplayed(this, new MessageEventArgs(image, text));
+ }
+
+ this.self = self;
+ }
+
+ /// Triggers the message acknowledged event
+ public void Dispose() {
+ EventHandler? messageAcknowledged = self.MessageAcknowledged;
+ if(messageAcknowledged != null) {
+ messageAcknowledged(this, EventArgs.Empty);
+ }
+ }
+
+ /// Message service the scope belongs to
+ private AvaloniaMessagePresenter self;
+
+ }
+
+ #endregion // class MessageScope
+
+ /// Triggered when a message is displayed to the user
+ public event EventHandler? MessageDisplaying;
+
+ /// Triggered when the user has acknowledged the current message
+ public event EventHandler? MessageAcknowledged;
+
+ /// Initializes a new Avalonia message service
+ /// Used to determine the current top-level window
+ public AvaloniaMessagePresenter(IActiveWindowTracker tracker) {
+ this.tracker = tracker;
+ }
+
+ /// Asks the user a question that can be answered via several buttons
+ /// Image that will be shown on the message box
+ /// Text that will be shown to the user
+ /// Buttons available for the user to click on
+ /// The button the user has clicked on
+ public Task ShowQuestionAsync(
+ MessageBoxIcon image, MessageText text, MessageBoxButtons buttons
+ ) {
+ using(var scope = new MessageScope(this, image, text)) {
+ MsBox.Avalonia.Base.IMsBox messageBox = (
+ MsBox.Avalonia.MessageBoxManager.GetMessageBoxStandard(
+ new MsBox.Avalonia.Dto.MessageBoxStandardParams() {
+ ContentTitle = text.Caption,
+ ContentHeader = text.Message,
+ ContentMessage = text.Details ?? string.Empty,
+ ButtonDefinitions = buttons,
+ Icon = image,
+ WindowStartupLocation = WindowStartupLocation.CenterOwner
+ }
+ )
+ );
+ return messageBox.ShowAsync(); // TODO: Make modal to current or main window
+ }
+ }
+
+ /// Displays a notification to the user
+ /// Image that will be shown on the message bx
+ /// Text that will be shown to the user
+ public Task ShowNotificationAsync(MessageBoxIcon image, MessageText text) {
+ using(var scope = new MessageScope(this, image, text)) {
+ MsBox.Avalonia.Base.IMsBox messageBox = (
+ MsBox.Avalonia.MessageBoxManager.GetMessageBoxStandard(
+ new MsBox.Avalonia.Dto.MessageBoxStandardParams() {
+ ContentTitle = text.Caption,
+ ContentHeader = text.Message,
+ ContentMessage = text.Details ?? string.Empty,
+ ButtonDefinitions = MessageBoxButtons.Ok,
+ Icon = image,
+ WindowStartupLocation = WindowStartupLocation.CenterOwner
+ }
+ )
+ );
+
+ Window? activeWindow = this.tracker.ActiveWindow;
+ if(activeWindow == null) {
+ return messageBox.ShowAsync();
+ } else {
+ //return messageBox.ShowAsPopupAsync(activeWindow);
+ return messageBox.ShowWindowDialogAsync(activeWindow);
+ }
+ }
+ }
+
+ /// Reports an error using the system's message box functions
+ /// Title of the message box
+ /// Message text that will be displayed
+ public static void FallbackReportError(string title, string message) {
+ // TODO: Escape quotes for the command-line tools
+ // TODO: Wait for the child process to exit so display is certain
+
+ if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
+ MessageBoxW(IntPtr.Zero, message, title, MB_OK | MB_ICONEXCLAMATION);
+ } else if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
+ Process.Start("zenity", $"--error --title=\"{title}\" --text=\"{message}\"");
+ } else if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
+ Process.Start("osascript", $"-e 'display dialog \"{message}\" with title \"{title}\" with icon stop'");
+ }
+ }
+
+ /// Windows only: display a message box with an OK button
+#if NET6_0_OR_GREATER
+ [SupportedOSPlatform("windows")]
+#endif
+ private const uint MB_OK = 0x00000000;
+
+ /// Windows only: display a message box with an Exclamation icon
+#if NET6_0_OR_GREATER
+ [SupportedOSPlatform("windows")]
+#endif
+ private const uint MB_ICONEXCLAMATION = 0x00000030;
+
+ /// Windows only: displays a native Windows message box
+ /// Handle of the window that owns the message box
+ /// Text that should be in the message box
+ /// Caption or window title of the message box
+ /// Which icons and buttons that message box should have
+ /// How the user closed the message box and which button they clicked
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
+#if NET6_0_OR_GREATER
+ [SupportedOSPlatform("windows")]
+#endif
+ private static extern int MessageBoxW(IntPtr parentWindowHandle, string text, string caption, uint type);
+
+ // Provides the currently active top-level window
+ private IActiveWindowTracker tracker;
+
+ }
+
+} // namespace Nuclex.Avalonia.Messages
+