├── _config.yml ├── src ├── img │ ├── wizard.png │ ├── basic-dialog.png │ ├── child-window.png │ ├── message-box.png │ ├── sample-app.png │ ├── message-box-checkbox.png │ └── JamSoftLogo-Splat513x513.png ├── JamSoft.AvaloniaUI.Dialogs │ ├── Assets │ │ ├── add.png │ │ ├── ban.png │ │ ├── info.png │ │ ├── wifi.png │ │ ├── back-up.png │ │ ├── customize.png │ │ ├── database.png │ │ ├── battery-half.png │ │ ├── check-circle.png │ │ ├── cross-circle.png │ │ ├── exclamation.png │ │ ├── folder-open.png │ │ ├── interrogation.png │ │ ├── diamond-exclamation.png │ │ └── CloseIcon │ │ │ ├── icons8-close-120.png │ │ │ ├── icons8-close-240.png │ │ │ ├── icons8-close-30.png │ │ │ ├── icons8-close-480.png │ │ │ ├── icons8-close-60.png │ │ │ ├── icons8-close-90.png │ │ │ ├── iOS │ │ │ ├── icons8-close-30(@1x).png │ │ │ ├── icons8-close-60(@2x).png │ │ │ └── icons8-close-90(@3x).png │ │ │ └── Android │ │ │ ├── icons8-close-23(-ldpi).png │ │ │ ├── icons8-close-30(-mdpi).png │ │ │ ├── icons8-close-45(-hdpi).png │ │ │ ├── icons8-close-60(-xhdpi).png │ │ │ ├── icons8-close-90(-xxhdpi).png │ │ │ └── icons8-close-120(-xxxhdpi).png │ ├── JamSoftLogo-Splat513x513.png │ ├── ViewModels │ │ ├── IWizardViewModel.cs │ │ ├── WizardViewModel.cs │ │ ├── IWindowPositionAware.cs │ │ ├── IChildWindowViewModel.cs │ │ ├── IDialogResultVmHelper.cs │ │ ├── IDialogViewModel.cs │ │ ├── ChildWindowViewModel.cs │ │ ├── IMsgBoxViewModel.cs │ │ ├── DialogViewModel.cs │ │ └── MsgBoxViewModel.cs │ ├── Events │ │ ├── UnregisterCallback.cs │ │ ├── IWeakEventHandler.cs │ │ ├── RequestCloseDialogEventArgs.cs │ │ ├── EventHandlerUtils.cs │ │ └── WeakEventHandler.cs │ ├── Views │ │ ├── MsgBoxView.axaml.cs │ │ ├── ChildWindow.axaml │ │ ├── MsgBoxView.axaml │ │ ├── DialogWindow.axaml.cs │ │ ├── MsgBoxWindow.axaml.cs │ │ ├── DialogWindow.axaml │ │ ├── ChildWindow.axaml.cs │ │ └── MsgBoxWindow.axaml │ ├── Themes │ │ ├── MsgBoxStyles.axaml │ │ ├── Default.axaml │ │ ├── ModalStyle.axaml │ │ ├── ChildStyle.axaml │ │ ├── WizardStyle.axaml │ │ └── WizardStepStyle.axaml │ ├── MsgBox │ │ ├── MsgBoxButton.cs │ │ ├── MsgBoxButtonResult.cs │ │ ├── MsgBoxResult.cs │ │ ├── IconResolver.cs │ │ └── MsgBoxImage.cs │ ├── DialogServiceConfiguration.cs │ ├── DialogServiceFactory.cs │ ├── IMessageBoxService.cs │ ├── Commands │ │ └── DelegateCommand.cs │ ├── MessageBoxService.cs │ ├── Controls │ │ ├── WizardStep.cs │ │ └── Wizard.cs │ ├── JamSoft.AvaloniaUI.Dialogs.csproj │ ├── Helpers │ │ ├── CommonFiltersExtensionMethods.cs │ │ └── CommonFilters.cs │ ├── IDialogService.cs │ └── DialogService.cs ├── JamSoft.AvaloniaUI.Dialogs.Sample │ ├── Assets │ │ └── avalonia-logo.ico │ ├── ViewModels │ │ ├── ViewModelBase.cs │ │ ├── SirNotAppearingInThisAppViewModel.cs │ │ ├── ComboBoxItemViewModel.cs │ │ ├── MyDialogViewModel.cs │ │ ├── MyChildWindowViewModel.cs │ │ ├── CustomBaseChildWindowViewModel.cs │ │ ├── MyWizardViewModel.cs │ │ └── MainWindowViewModel.cs │ ├── Roots.xml │ ├── Models │ │ └── MyUserSettings.cs │ ├── Views │ │ ├── MyWizardView.axaml.cs │ │ ├── MyDialogView.axaml.cs │ │ ├── MyChildWindowView.axaml.cs │ │ ├── CustomBaseChildWindowView.axaml.cs │ │ ├── MainWindow.axaml.cs │ │ ├── MyDialogView.axaml │ │ ├── MyChildWindowView.axaml │ │ ├── CustomBaseChildWindowView.axaml │ │ ├── MyWizardView.axaml │ │ └── MainWindow.axaml │ ├── App.axaml.cs │ ├── app.manifest │ ├── Program.cs │ ├── BootStrapper.cs │ ├── App.axaml │ ├── JamSoft.AvaloniaUI.Dialogs.Sample.csproj │ └── .gitignore └── JamSoft.AvaloniaUI.Dialogs.sln ├── .gitpod.yml ├── .gitlab-ci.yml ├── .gitignore └── LICENSE /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /src/img/wizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/img/wizard.png -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: gitpod/workspace-dotnet 2 | 3 | tasks: 4 | - init: dotnet build 5 | command: dotnet run 6 | -------------------------------------------------------------------------------- /src/img/basic-dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/img/basic-dialog.png -------------------------------------------------------------------------------- /src/img/child-window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/img/child-window.png -------------------------------------------------------------------------------- /src/img/message-box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/img/message-box.png -------------------------------------------------------------------------------- /src/img/sample-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/img/sample-app.png -------------------------------------------------------------------------------- /src/img/message-box-checkbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/img/message-box-checkbox.png -------------------------------------------------------------------------------- /src/img/JamSoftLogo-Splat513x513.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/img/JamSoftLogo-Splat513x513.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/add.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/ban.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/ban.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/info.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/wifi.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/back-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/back-up.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/customize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/customize.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/database.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/battery-half.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/battery-half.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/check-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/check-circle.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/cross-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/cross-circle.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/exclamation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/exclamation.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/folder-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/folder-open.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/interrogation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/interrogation.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/JamSoftLogo-Splat513x513.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/JamSoftLogo-Splat513x513.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/diamond-exclamation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/diamond-exclamation.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Assets/avalonia-logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs.Sample/Assets/avalonia-logo.ico -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-120.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-240.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-30.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-480.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-480.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-60.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/icons8-close-90.png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | 3 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.ViewModels; 4 | 5 | public class ViewModelBase : ReactiveObject 6 | { 7 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/iOS/icons8-close-30(@1x).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/iOS/icons8-close-30(@1x).png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/iOS/icons8-close-60(@2x).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/iOS/icons8-close-60(@2x).png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/iOS/icons8-close-90(@3x).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/iOS/icons8-close-90(@3x).png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-23(-ldpi).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-23(-ldpi).png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-30(-mdpi).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-30(-mdpi).png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-45(-hdpi).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-45(-hdpi).png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-60(-xhdpi).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-60(-xhdpi).png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-90(-xxhdpi).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-90(-xxhdpi).png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-120(-xxxhdpi).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsoft/JamSoft.AvaloniaUI.Dialogs/HEAD/src/JamSoft.AvaloniaUI.Dialogs/Assets/CloseIcon/Android/icons8-close-120(-xxxhdpi).png -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/ViewModels/IWizardViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs.ViewModels; 2 | 3 | /// 4 | /// Defines a contract for a Wizard view model 5 | /// 6 | public interface IWizardViewModel : IChildWindowViewModel { } -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: mcr.microsoft.com/dotnet/core/sdk:latest 2 | 3 | stages: 4 | - build 5 | 6 | build: 7 | stage: build 8 | script: 9 | - "dotnet build src\\JamSoft.AvaloniaUI.Dialogs.sln" 10 | artifacts: 11 | paths: 12 | - bin/ -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/ViewModels/SirNotAppearingInThisAppViewModel.cs: -------------------------------------------------------------------------------- 1 | using JamSoft.AvaloniaUI.Dialogs.ViewModels; 2 | 3 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.ViewModels; 4 | 5 | public class SirNotAppearingInThisAppViewModel : ChildWindowViewModel 6 | { 7 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Roots.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Events/UnregisterCallback.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs.Events; 2 | 3 | /// 4 | /// The unregister delegate 5 | /// 6 | /// 7 | public delegate void UnregisterCallback(EventHandler eventHandler) where TE : EventArgs; -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/ViewModels/WizardViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | using JamSoft.AvaloniaUI.Dialogs.Commands; 3 | 4 | namespace JamSoft.AvaloniaUI.Dialogs.ViewModels; 5 | 6 | /// 7 | /// A base implementation of the IWizardViewModel interface 8 | /// 9 | public abstract class WizardViewModel : ChildWindowViewModel, IWizardViewModel { } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Models/MyUserSettings.cs: -------------------------------------------------------------------------------- 1 | using JamSoft.Helpers.Configuration; 2 | 3 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.Models; 4 | 5 | public class MyUserSettings : SettingsBase 6 | { 7 | public double Left { get; set; } 8 | public double Top { get; set; } 9 | public double Height { get; set; } 10 | public double Width { get; set; } 11 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Events/IWeakEventHandler.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs.Events; 2 | 3 | /// 4 | /// The weak event handler interface 5 | /// 6 | /// 7 | public interface IWeakEventHandler where TE : EventArgs 8 | { 9 | /// 10 | /// The event handler 11 | /// 12 | EventHandler Handler { get; } 13 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Views/MyWizardView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Markup.Xaml; 3 | 4 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.Views; 5 | 6 | public partial class MyWizardView : UserControl 7 | { 8 | public MyWizardView() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | private void InitializeComponent() 14 | { 15 | AvaloniaXamlLoader.Load(this); 16 | } 17 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Views/MyDialogView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | 5 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.Views; 6 | 7 | public partial class MyDialogView : UserControl 8 | { 9 | public MyDialogView() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | private void InitializeComponent() 15 | { 16 | AvaloniaXamlLoader.Load(this); 17 | } 18 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.*~ 3 | project.lock.json 4 | .DS_Store 5 | *.pyc 6 | nupkg/ 7 | 8 | # Visual Studio Code 9 | .vscode 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.userosscache 15 | *.sln.docstates 16 | *.snk 17 | 18 | # Build results 19 | [Dd]ebug/ 20 | [Dd]ebugPublic/ 21 | [Rr]elease/ 22 | [Rr]eleases/ 23 | x64/ 24 | x86/ 25 | build/ 26 | bld/ 27 | [Bb]in/ 28 | [Oo]bj/ 29 | [Oo]ut/ 30 | msbuild.log 31 | msbuild.err 32 | msbuild.wrn 33 | 34 | src/.idea/ 35 | .vs -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Views/MyChildWindowView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | 5 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.Views; 6 | 7 | public partial class MyChildWindowView : UserControl 8 | { 9 | public MyChildWindowView() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | private void InitializeComponent() 15 | { 16 | AvaloniaXamlLoader.Load(this); 17 | } 18 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Views/MsgBoxView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | 5 | namespace JamSoft.AvaloniaUI.Dialogs.Views; 6 | 7 | /// 8 | /// The message box view 9 | /// 10 | public partial class MsgBoxView : UserControl 11 | { 12 | /// 13 | /// The default constructor 14 | /// 15 | public MsgBoxView() 16 | { 17 | InitializeComponent(); 18 | } 19 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Views/CustomBaseChildWindowView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | 5 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.Views; 6 | 7 | public partial class CustomBaseChildWindowView : UserControl 8 | { 9 | public CustomBaseChildWindowView() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | private void InitializeComponent() 15 | { 16 | AvaloniaXamlLoader.Load(this); 17 | } 18 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Views/MainWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia; 3 | using Avalonia.Controls; 4 | using Avalonia.Interactivity; 5 | using JamSoft.AvaloniaUI.Dialogs.Sample.Models; 6 | 7 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.Views; 8 | 9 | public partial class MainWindow : Window 10 | { 11 | public MainWindow() 12 | { 13 | InitializeComponent(); 14 | 15 | this.AttachDevTools(); 16 | } 17 | 18 | private void TopLevel_OnClosed(object? sender, EventArgs e) 19 | { 20 | MyUserSettings.Save(); 21 | } 22 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Themes/MsgBoxStyles.axaml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 8 | 11 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Views/MyDialogView.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/ViewModels/ComboBoxItemViewModel.cs: -------------------------------------------------------------------------------- 1 | using JamSoft.Helpers.AvaloniaUI.Patterns.Mvvm; 2 | using ReactiveUI; 3 | 4 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.ViewModels; 5 | 6 | public class ComboBoxItemViewModel : AvaloniaViewModelBase 7 | { 8 | private string? _name; 9 | private object? _value; 10 | 11 | public string? Name 12 | { 13 | get => _name; 14 | set => this.RaiseAndSetIfChanged(ref _name, value); 15 | } 16 | 17 | public object? Value 18 | { 19 | get => _value; 20 | set => this.RaiseAndSetIfChanged(ref _value, value); 21 | } 22 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/MsgBox/MsgBoxButton.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs.MsgBox; 2 | 3 | /// 4 | /// The message box button enum 5 | /// 6 | public enum MsgBoxButton 7 | { 8 | /// 9 | /// Show the OK button 10 | /// 11 | Ok, 12 | 13 | /// 14 | /// Show the OK and Cancel buttons 15 | /// 16 | OkCancel, 17 | 18 | /// 19 | /// Show the Yes and No buttons 20 | /// 21 | YesNo, 22 | 23 | /// 24 | /// Show the Yes, No and Cancel buttons 25 | /// 26 | YesNoCancel 27 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Themes/Default.axaml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/DialogServiceConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs; 2 | 3 | /// 4 | /// Provides startup configuration details 5 | /// 6 | public class DialogServiceConfiguration 7 | { 8 | /// 9 | /// Set the application name in titles 10 | /// 11 | public bool UseApplicationNameInTitle { get; set; } 12 | 13 | /// 14 | /// The application name to display in titles 15 | /// 16 | public string? ApplicationName { get; set; } 17 | 18 | /// 19 | /// All 20 | /// 21 | public string? ViewsAssemblyName { get; set; } 22 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/ViewModels/IWindowPositionAware.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace JamSoft.AvaloniaUI.Dialogs.ViewModels; 4 | 5 | /// 6 | /// The window position aware interface 7 | /// 8 | public interface IWindowPositionAware 9 | { 10 | /// 11 | /// The child window startup location 12 | /// 13 | WindowStartupLocation Location { get; set; } 14 | 15 | /// 16 | /// The child window requested top value 17 | /// 18 | double RequestedTop { get; set; } 19 | 20 | /// 21 | /// The child window requested left value 22 | /// 23 | double RequestedLeft { get; set; } 24 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/MsgBox/MsgBoxButtonResult.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs.MsgBox; 2 | 3 | /// 4 | /// The message box result enum 5 | /// 6 | public enum MsgBoxButtonResult 7 | { 8 | /// 9 | /// The default value 10 | /// 11 | None, 12 | 13 | /// 14 | /// The OK value 15 | /// 16 | Ok, 17 | 18 | /// 19 | /// The Cancel value 20 | /// 21 | Cancel, 22 | 23 | /// 24 | /// The Yes value 25 | /// 26 | Yes, 27 | 28 | /// 29 | /// The No value 30 | /// 31 | No 32 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/ViewModels/MyDialogViewModel.cs: -------------------------------------------------------------------------------- 1 | using JamSoft.AvaloniaUI.Dialogs.ViewModels; 2 | 3 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.ViewModels; 4 | 5 | public class MyDialogViewModel : DialogViewModel 6 | { 7 | private string? _dialogMessage; 8 | 9 | public string? DialogMessage 10 | { 11 | get => _dialogMessage; 12 | set => RaiseAndSetIfChanged(ref _dialogMessage , value); 13 | } 14 | 15 | public override bool CanAccept() 16 | { 17 | return !string.IsNullOrWhiteSpace(DialogMessage); 18 | } 19 | 20 | public override bool CanCancel() 21 | { 22 | return string.IsNullOrWhiteSpace(DialogMessage); 23 | } 24 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Events/RequestCloseDialogEventArgs.cs: -------------------------------------------------------------------------------- 1 | using JamSoft.AvaloniaUI.Dialogs.MsgBox; 2 | 3 | namespace JamSoft.AvaloniaUI.Dialogs.Events; 4 | 5 | /// 6 | /// The request close dialog event 7 | /// 8 | public class RequestCloseDialogEventArgs : EventArgs 9 | { 10 | /// 11 | /// The dialog result 12 | /// 13 | public bool DialogResult { get; set; } 14 | 15 | /// 16 | /// Default constructor 17 | /// 18 | /// the dialog result instance 19 | public RequestCloseDialogEventArgs(bool dialogresult) 20 | { 21 | DialogResult = dialogresult; 22 | } 23 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Themes/ModalStyle.axaml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/ViewModels/IChildWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media; 2 | 3 | namespace JamSoft.AvaloniaUI.Dialogs.ViewModels; 4 | 5 | /// 6 | /// The child window view model interface 7 | /// 8 | public interface IChildWindowViewModel : IDialogViewModel, IWindowPositionAware 9 | { 10 | /// 11 | /// The child window title 12 | /// 13 | string? ChildWindowTitle { get; set; } 14 | 15 | /// 16 | /// The child window width 17 | /// 18 | double RequestedWidth { get; set; } 19 | 20 | /// 21 | /// The child window height 22 | /// 23 | double RequestedHeight { get; set; } 24 | 25 | /// 26 | /// The close icon 27 | /// 28 | IImage CloseIcon { get; set; } 29 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/App.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls.ApplicationLifetimes; 3 | using Avalonia.Markup.Xaml; 4 | using JamSoft.AvaloniaUI.Dialogs.Sample.ViewModels; 5 | using JamSoft.AvaloniaUI.Dialogs.Sample.Views; 6 | using Splat; 7 | 8 | namespace JamSoft.AvaloniaUI.Dialogs.Sample; 9 | 10 | public partial class App : Application 11 | { 12 | public override void Initialize() 13 | { 14 | AvaloniaXamlLoader.Load(this); 15 | } 16 | 17 | public override void OnFrameworkInitializationCompleted() 18 | { 19 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 20 | { 21 | desktop.MainWindow = new MainWindow 22 | { 23 | DataContext = Locator.Current.GetService() 24 | }; 25 | } 26 | 27 | base.OnFrameworkInitializationCompleted(); 28 | } 29 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/DialogServiceFactory.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs; 2 | 3 | /// 4 | /// The dialog service factory 5 | /// 6 | public static class DialogServiceFactory 7 | { 8 | /// 9 | /// Creates a new instance of the dialog service using the provided configuration object 10 | /// 11 | /// The configuration object instance 12 | /// a new instance of 13 | public static IDialogService Create(DialogServiceConfiguration config) 14 | { 15 | return new DialogService(config); 16 | } 17 | 18 | /// 19 | /// Creates a new instance of the messagebox service 20 | /// 21 | /// a new instance of 22 | public static IMessageBoxService CreateMessageBoxService() 23 | { 24 | return new MessageBoxService(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/ViewModels/IDialogResultVmHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | using JamSoft.AvaloniaUI.Dialogs.Commands; 3 | using JamSoft.AvaloniaUI.Dialogs.Events; 4 | 5 | namespace JamSoft.AvaloniaUI.Dialogs.ViewModels; 6 | 7 | /// 8 | /// The dialog result helper 9 | /// 10 | public interface IDialogResultVmHelper 11 | { 12 | /// 13 | /// Occurs when [request close dialog] event is fired. 14 | /// 15 | event EventHandler RequestCloseDialog; 16 | 17 | /// 18 | /// Gets or sets the accept command. 19 | /// 20 | /// 21 | /// The accept command. 22 | /// 23 | ICommand AcceptCommand { get; set; } 24 | 25 | /// 26 | /// Gets or sets the cancel command. 27 | /// 28 | /// 29 | /// The cancel command. 30 | /// 31 | ICommand CancelCommand { get; set; } 32 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/MsgBox/MsgBoxResult.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs.MsgBox; 2 | 3 | /// 4 | /// The message box result enum 5 | /// 6 | public sealed class MsgBoxResult 7 | { 8 | /// 9 | /// The message box button result enum 10 | /// 11 | public MsgBoxButtonResult ButtonResult { get; } 12 | 13 | /// 14 | /// The message box check box result 15 | /// 16 | public bool CheckBoxResult { get; } 17 | 18 | private MsgBoxResult(bool checkBoxResult, MsgBoxButtonResult buttonResult) 19 | { 20 | CheckBoxResult = checkBoxResult; 21 | ButtonResult = buttonResult; 22 | } 23 | 24 | /// 25 | /// Creates a new message box result instance 26 | /// 27 | /// 28 | /// 29 | /// 30 | public static MsgBoxResult CreateResult(bool checkBoxChecked, MsgBoxButtonResult buttonResult) => new(checkBoxChecked, buttonResult); 31 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 James Green 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Views/MyChildWindowView.axaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/ViewModels/IDialogViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace JamSoft.AvaloniaUI.Dialogs.ViewModels; 4 | 5 | /// 6 | /// The dialog view model interface 7 | /// 8 | public interface IDialogViewModel : INotifyPropertyChanged, IDialogResultVmHelper 9 | { 10 | /// 11 | /// The dialog accept command text 12 | /// 13 | string? AcceptCommandText { get; set; } 14 | 15 | /// 16 | /// The dialog cancel command text 17 | /// 18 | string? CancelCommandText { get; set; } 19 | 20 | /// 21 | /// Implements the logic that controls the accept command execution validation 22 | /// 23 | /// 24 | bool CanAccept(); 25 | 26 | /// 27 | /// Implements the logic that controls the cancel command execution validation 28 | /// 29 | /// 30 | bool CanCancel(); 31 | 32 | /// 33 | /// If true, the cancel button will not be shown 34 | /// 35 | bool HideCancelButton { get; set; } 36 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Program.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.ReactiveUI; 3 | using System; 4 | using JamSoft.AvaloniaUI.Dialogs.Sample.Models; 5 | using Splat; 6 | 7 | namespace JamSoft.AvaloniaUI.Dialogs.Sample; 8 | 9 | class Program 10 | { 11 | // Initialization code. Don't use any Avalonia, third-party APIs or any 12 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 13 | // yet and stuff might break. 14 | [STAThread] 15 | public static void Main(string[] args) 16 | { 17 | RegisterDependencies(); 18 | 19 | MyUserSettings.Load(AppDomain.CurrentDomain.BaseDirectory); 20 | 21 | BuildAvaloniaApp() 22 | .StartWithClassicDesktopLifetime(args); 23 | } 24 | 25 | private static void RegisterDependencies() => 26 | BootStrapper.Register(Locator.CurrentMutable, Locator.Current); 27 | 28 | // Avalonia configuration, don't remove; also used by visual designer. 29 | public static AppBuilder BuildAvaloniaApp() 30 | => AppBuilder.Configure() 31 | .UsePlatformDetect() 32 | .LogToTrace() 33 | .UseReactiveUI(); 34 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/Views/CustomBaseChildWindowView.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | CUSTOM CHILD VIEW 9 | This is a completely custom dialog. The view model implements IChildWindowViewModel and the accompanying view is auto discovered based on the ViewModel / View naming convention. 10 | A CustomBaseChildWindowViewModel is joined with a CustomBaseChildWindowView instance at runtime. 11 | The same approach can be taken with modal dialogs by implementing the IDialogViewModel interface and calling the ShowDialog method on the IDialogService. 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/BootStrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using JamSoft.AvaloniaUI.Dialogs.Sample.ViewModels; 3 | using JamSoft.AvaloniaUI.Dialogs.ViewModels; 4 | using Splat; 5 | 6 | namespace JamSoft.AvaloniaUI.Dialogs.Sample; 7 | 8 | public static class BootStrapper 9 | { 10 | public static void Register(IMutableDependencyResolver services, IReadonlyDependencyResolver resolver) 11 | { 12 | services.RegisterLazySingleton(() => DialogServiceFactory.Create(new DialogServiceConfiguration 13 | { 14 | ApplicationName = "Dialog Sample App", 15 | UseApplicationNameInTitle = true, 16 | ViewsAssemblyName = Assembly.GetExecutingAssembly().GetName().Name 17 | })); 18 | 19 | services.RegisterLazySingleton(DialogServiceFactory.CreateMessageBoxService); 20 | 21 | services.Register(() => new MainWindowViewModel(resolver.GetService()!, resolver.GetService()!)); 22 | services.Register(() => new MyDialogViewModel()); 23 | services.Register(() => new MyChildWindowViewModel()); 24 | services.Register(() => new CustomBaseChildWindowViewModel()); 25 | services.Register(() => new SirNotAppearingInThisAppViewModel()); // this has no matching view on purpose 26 | services.Register(() => new MyWizardViewModel()); 27 | } 28 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/IMessageBoxService.cs: -------------------------------------------------------------------------------- 1 | using JamSoft.AvaloniaUI.Dialogs.MsgBox; 2 | using JamSoft.AvaloniaUI.Dialogs.ViewModels; 3 | 4 | namespace JamSoft.AvaloniaUI.Dialogs; 5 | 6 | /// 7 | /// The message box service interface 8 | /// 9 | public interface IMessageBoxService 10 | { 11 | /// 12 | /// Show a message box with the specified parameters 13 | /// 14 | /// the messagebox caption 15 | /// the message text 16 | /// the button configuration 17 | /// the icon enum 18 | /// the negative response button text value 19 | /// the positive response button text used for Yes/OK buttons 20 | /// the cancel response button text 21 | /// The checkbox text 22 | /// the response 23 | Task Show(string caption, string messageBoxText, MsgBoxButton button, MsgBoxImage icon = MsgBoxImage.None, string? noButtonText = null, string? yesButtonText = null, string? cancelButtonText = null, string? checkBoxText = null); 24 | 25 | /// 26 | /// Show a message box with the specified view model 27 | /// 28 | /// the view model instance 29 | /// the response 30 | Task Show(IMsgBoxViewModel viewModel); 31 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Events/EventHandlerUtils.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs.Events; 2 | 3 | /// 4 | /// Event handler extensions 5 | /// 6 | public static class EventHandlerUtils 7 | { 8 | /// 9 | /// Makes a weak handler 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static EventHandler? MakeWeak(this EventHandler eventHandler, UnregisterCallback unregister) where TE : EventArgs 16 | { 17 | if (eventHandler == null) 18 | { 19 | throw new ArgumentNullException(nameof(eventHandler)); 20 | } 21 | 22 | if (eventHandler.Method.IsStatic || eventHandler.Target == null) 23 | { 24 | throw new ArgumentException(@"Only instance methods are supported.", nameof(eventHandler)); 25 | } 26 | 27 | if (eventHandler.Method.DeclaringType != null) 28 | { 29 | var wehType = typeof(WeakEventHandler<,>).MakeGenericType(eventHandler.Method.DeclaringType, typeof(TE)); 30 | 31 | var wehConstructor = wehType.GetConstructor(new Type[] 32 | { 33 | typeof(EventHandler), typeof(UnregisterCallback) 34 | }); 35 | 36 | if (wehConstructor != null) 37 | { 38 | IWeakEventHandler weh = (IWeakEventHandler)wehConstructor.Invoke(new object[] { eventHandler, unregister }); 39 | 40 | return weh.Handler; 41 | } 42 | } 43 | 44 | return null; 45 | } 46 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Views/ChildWindow.axaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 35 | 36 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Commands/DelegateCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | 3 | namespace JamSoft.AvaloniaUI.Dialogs.Commands; 4 | 5 | /// 6 | /// The default delegate command 7 | /// 8 | public class DelegateCommand : ICommand 9 | { 10 | private readonly Func? _canExecute; 11 | private readonly Action? _execute; 12 | 13 | /// 14 | /// The can execute changed handler 15 | /// 16 | public event EventHandler? CanExecuteChanged; 17 | 18 | /// 19 | /// The default constructor 20 | /// 21 | /// 22 | /// 23 | public DelegateCommand(Action? execute, Func? canExecute = null) 24 | { 25 | _execute = execute; 26 | _canExecute = canExecute; 27 | } 28 | 29 | /// 30 | /// The can execute method 31 | /// 32 | /// 33 | /// 34 | public bool CanExecute(object parameter) 35 | { 36 | if (_canExecute == null) return true; 37 | return _canExecute(); 38 | } 39 | 40 | /// 41 | /// The execute method 42 | /// 43 | /// 44 | public void Execute(object parameter) 45 | { 46 | if (_execute == null) return; 47 | _execute(); 48 | } 49 | 50 | /// 51 | /// Raises the can execute change event 52 | /// 53 | public void RaiseCanExecuteChanged() 54 | { 55 | if( CanExecuteChanged != null ) 56 | { 57 | CanExecuteChanged(this, EventArgs.Empty); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JamSoft.AvaloniaUI.Dialogs.Sample", "JamSoft.AvaloniaUI.Dialogs.Sample\JamSoft.AvaloniaUI.Dialogs.Sample.csproj", "{E96BA9F0-28A7-424B-8B7B-3F36C7D97BAF}" 4 | EndProject 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JamSoft.AvaloniaUI.Dialogs", "JamSoft.AvaloniaUI.Dialogs\JamSoft.AvaloniaUI.Dialogs.csproj", "{C9D05C1A-6A85-4B87-A69E-D05D352BAB67}" 6 | EndProject 7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{644815C4-7C07-43AE-9FBC-01A67BE642C6}" 8 | ProjectSection(SolutionItems) = preProject 9 | ..\README.md = ..\README.md 10 | ..\.gitlab-ci.yml = ..\.gitlab-ci.yml 11 | ..\_config.yml = ..\_config.yml 12 | EndProjectSection 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {E96BA9F0-28A7-424B-8B7B-3F36C7D97BAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {E96BA9F0-28A7-424B-8B7B-3F36C7D97BAF}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {E96BA9F0-28A7-424B-8B7B-3F36C7D97BAF}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {E96BA9F0-28A7-424B-8B7B-3F36C7D97BAF}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {C9D05C1A-6A85-4B87-A69E-D05D352BAB67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {C9D05C1A-6A85-4B87-A69E-D05D352BAB67}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {C9D05C1A-6A85-4B87-A69E-D05D352BAB67}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {C9D05C1A-6A85-4B87-A69E-D05D352BAB67}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Views/MsgBoxView.axaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 32 | 33 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/MsgBox/IconResolver.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media.Imaging; 2 | using Avalonia.Platform; 3 | 4 | namespace JamSoft.AvaloniaUI.Dialogs.MsgBox; 5 | 6 | /// 7 | /// Resolves the icon for the message box 8 | /// 9 | public static class IconResolver 10 | { 11 | private static Dictionary _icons = new() 12 | { 13 | { MsgBoxImage.Asterisk, "exclamation.png" }, 14 | { MsgBoxImage.Exclamation, "diamond-exclamation.png" }, 15 | { MsgBoxImage.Hand, "cross-circle.png" }, 16 | { MsgBoxImage.Stop, "cross-circle.png" }, 17 | { MsgBoxImage.Error, "cross-circle.png" }, 18 | { MsgBoxImage.Question, "interrogation.png" }, 19 | { MsgBoxImage.Warning, "diamond-exclamation.png" }, 20 | { MsgBoxImage.Information, "info.png" }, 21 | { MsgBoxImage.Custom, "Custom" }, 22 | { MsgBoxImage.Success, "check-circle.png" }, 23 | { MsgBoxImage.Battery, "battery-half.png" }, 24 | { MsgBoxImage.Database, "database.png" }, 25 | { MsgBoxImage.Folder, "folder-open.png" }, 26 | { MsgBoxImage.Forbidden, "ban.png" }, 27 | { MsgBoxImage.Plus, "add.png" }, 28 | { MsgBoxImage.Setting, "customize.png" }, 29 | { MsgBoxImage.Wifi, "wifi.png" } 30 | }; 31 | 32 | /// 33 | /// Resolves the icon for the message box 34 | /// 35 | /// 36 | /// 37 | public static Bitmap? Resolve(MsgBoxImage icon) 38 | { 39 | if (_icons.TryGetValue(icon, out var iconName)) 40 | { 41 | return new Bitmap(AssetLoader.Open(new Uri($"avares://JamSoft.AvaloniaUI.Dialogs/Assets/{iconName}"))); 42 | } 43 | 44 | return null; 45 | } 46 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Views/DialogWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | using JamSoft.AvaloniaUI.Dialogs.Events; 5 | using JamSoft.AvaloniaUI.Dialogs.ViewModels; 6 | 7 | namespace JamSoft.AvaloniaUI.Dialogs.Views; 8 | 9 | /// 10 | /// The default dialog window 11 | /// 12 | public partial class DialogWindow : Window 13 | { 14 | private bool _isClosed; 15 | 16 | /// 17 | /// The default constructor 18 | /// 19 | public DialogWindow() 20 | { 21 | InitializeComponent(); 22 | #if DEBUG 23 | this.AttachDevTools(); 24 | #endif 25 | this.FindControl("Host")!.DataContextChanged += DialogPresenterDataContextChanged; 26 | Closed += DialogWindowClosed; 27 | } 28 | 29 | void DialogWindowClosed(object? sender, EventArgs e) 30 | { 31 | Closed -= DialogWindowClosed; 32 | _isClosed = true; 33 | } 34 | 35 | private void DialogPresenterDataContextChanged(object? sender, EventArgs e) 36 | { 37 | var d = DataContext as IDialogResultVmHelper; 38 | 39 | if (d == null) 40 | { 41 | return; 42 | } 43 | 44 | d.RequestCloseDialog += new EventHandler(DialogResultTrueEvent) 45 | .MakeWeak(eh => d.RequestCloseDialog -= eh); 46 | } 47 | 48 | private void DialogResultTrueEvent(object? sender, RequestCloseDialogEventArgs eventargs) 49 | { 50 | // Important: Do not set DialogResult for a closed window 51 | // GC clears windows anyways and with MakeWeak it 52 | // closes out with IDialogResultVMHelper 53 | if (_isClosed) 54 | { 55 | return; 56 | } 57 | 58 | Close(eventargs.DialogResult); 59 | } 60 | 61 | private void InitializeComponent() 62 | { 63 | AvaloniaXamlLoader.Load(this); 64 | } 65 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Views/MsgBoxWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | using JamSoft.AvaloniaUI.Dialogs.Events; 5 | using JamSoft.AvaloniaUI.Dialogs.ViewModels; 6 | 7 | namespace JamSoft.AvaloniaUI.Dialogs.Views; 8 | 9 | /// 10 | /// The default dialog window 11 | /// 12 | public partial class MsgBoxWindow : Window 13 | { 14 | private bool _isClosed; 15 | 16 | /// 17 | /// The default constructor 18 | /// 19 | public MsgBoxWindow() 20 | { 21 | InitializeComponent(); 22 | #if DEBUG 23 | this.AttachDevTools(); 24 | #endif 25 | this.FindControl("Host")!.DataContextChanged += DialogPresenterDataContextChanged; 26 | Closed += DialogWindowClosed; 27 | } 28 | 29 | void DialogWindowClosed(object? sender, EventArgs e) 30 | { 31 | Closed -= DialogWindowClosed; 32 | _isClosed = true; 33 | } 34 | 35 | private void DialogPresenterDataContextChanged(object? sender, EventArgs e) 36 | { 37 | var d = DataContext as IDialogResultVmHelper; 38 | 39 | if (d == null) 40 | { 41 | return; 42 | } 43 | 44 | d.RequestCloseDialog += new EventHandler(DialogResultTrueEvent) 45 | .MakeWeak(eh => d.RequestCloseDialog -= eh); 46 | } 47 | 48 | private void DialogResultTrueEvent(object? sender, RequestCloseDialogEventArgs eventargs) 49 | { 50 | // Important: Do not set DialogResult for a closed window 51 | // GC clears windows anyways and with MakeWeak it 52 | // closes out with IDialogResultVMHelper 53 | if (_isClosed) 54 | { 55 | return; 56 | } 57 | 58 | Close(eventargs.DialogResult); 59 | } 60 | 61 | private void InitializeComponent() 62 | { 63 | AvaloniaXamlLoader.Load(this); 64 | } 65 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/App.axaml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/JamSoft.AvaloniaUI.Dialogs.Sample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | WinExe 4 | net8.0 5 | enable 6 | true 7 | app.manifest 8 | 12 9 | Assets\avalonia-logo.ico 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | MyWizardView.axaml 41 | Code 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/ViewModels/MyChildWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using JamSoft.AvaloniaUI.Dialogs.Events; 3 | using JamSoft.AvaloniaUI.Dialogs.Sample.Models; 4 | using JamSoft.AvaloniaUI.Dialogs.ViewModels; 5 | 6 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.ViewModels; 7 | 8 | public class MyChildWindowViewModel : ChildWindowViewModel 9 | { 10 | private string? _childMessage; 11 | private ObservableCollection? _comboboxItems; 12 | private ComboBoxItemViewModel? _selectedItem; 13 | 14 | public MyChildWindowViewModel() 15 | { 16 | RequestCloseDialog += OnRequestCloseDialog; 17 | 18 | ComboboxItems = new ObservableCollection 19 | { 20 | new ComboBoxItemViewModel { Name = string.Empty, Value = null }, 21 | new ComboBoxItemViewModel { Name = "Item One", Value = 1 }, 22 | new ComboBoxItemViewModel { Name = "Item Two", Value = 2 }, 23 | new ComboBoxItemViewModel { Name = "Item Three", Value = 3 } 24 | }; 25 | } 26 | 27 | public string? ChildMessage 28 | { 29 | get => _childMessage; 30 | set => RaiseAndSetIfChanged(ref _childMessage, value); 31 | } 32 | 33 | public ObservableCollection? ComboboxItems 34 | { 35 | get => _comboboxItems; 36 | set => RaiseAndSetIfChanged(ref _comboboxItems, value); 37 | } 38 | 39 | public ComboBoxItemViewModel? SelectedItem 40 | { 41 | get => _selectedItem; 42 | set => RaiseAndSetIfChanged(ref _selectedItem, value); 43 | } 44 | 45 | private void OnRequestCloseDialog(object? sender, RequestCloseDialogEventArgs e) 46 | { 47 | MyUserSettings.Instance.Top = RequestedTop; 48 | MyUserSettings.Instance.Left = RequestedLeft; 49 | MyUserSettings.Instance.Width = RequestedWidth; 50 | MyUserSettings.Instance.Height = RequestedHeight; 51 | 52 | RequestCloseDialog -= OnRequestCloseDialog; 53 | } 54 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/MsgBox/MsgBoxImage.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs.MsgBox; 2 | 3 | /// 4 | /// Specifies the icon to display in a message box 5 | /// 6 | public enum MsgBoxImage 7 | { 8 | /// 9 | /// Show no icon 10 | /// 11 | None, 12 | 13 | /// 14 | /// Show the Asterisk icon 15 | /// 16 | Asterisk, 17 | 18 | /// 19 | /// Show the Exclamation icon 20 | /// 21 | Exclamation, 22 | 23 | /// 24 | /// Show the Hand icon 25 | /// 26 | Hand, 27 | 28 | /// 29 | /// Show the Stop icon 30 | /// 31 | Stop, 32 | 33 | /// 34 | /// Show the Error icon 35 | /// 36 | Error, 37 | 38 | /// 39 | /// Show the Question icon 40 | /// 41 | Question, 42 | 43 | /// 44 | /// Show the Warning icon 45 | /// 46 | Warning, 47 | 48 | /// 49 | /// Show the Information icon 50 | /// 51 | Information, 52 | 53 | /// 54 | /// Show a custom icon 55 | /// 56 | Custom, 57 | 58 | /// 59 | /// Show the Success icon 60 | /// 61 | Success, 62 | 63 | /// 64 | /// Show the Battery icon 65 | /// 66 | Battery, 67 | 68 | /// 69 | /// Show the Database icon 70 | /// 71 | Database, 72 | 73 | /// 74 | /// Show the Folder icon 75 | /// 76 | Folder, 77 | 78 | /// 79 | /// Show the Forbidden icon 80 | /// 81 | Forbidden, 82 | 83 | /// 84 | /// Show the Plus icon 85 | /// 86 | Plus, 87 | 88 | /// 89 | /// Show the Setting icon 90 | /// 91 | Setting, 92 | 93 | /// 94 | /// Show the Wifi icon 95 | /// 96 | Wifi 97 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Events/WeakEventHandler.cs: -------------------------------------------------------------------------------- 1 | namespace JamSoft.AvaloniaUI.Dialogs.Events; 2 | 3 | /// 4 | /// The weak event handler 5 | /// 6 | /// 7 | /// 8 | public class WeakEventHandler : IWeakEventHandler where T : class where TE : EventArgs 9 | { 10 | private delegate void OpenEventHandler(T @this, object sender, TE e); 11 | 12 | private readonly WeakReference _mTargetRef; 13 | private readonly OpenEventHandler _mOpenHandler; 14 | private readonly EventHandler _mHandler; 15 | // ReSharper disable once NotAccessedField.Local 16 | private UnregisterCallback _mUnregister; 17 | 18 | /// 19 | /// The default constructor 20 | /// 21 | /// 22 | /// 23 | public WeakEventHandler(EventHandler eventHandler, UnregisterCallback unregister) 24 | { 25 | _mTargetRef = new WeakReference(eventHandler.Target); 26 | 27 | _mOpenHandler = (OpenEventHandler)Delegate.CreateDelegate( 28 | typeof(OpenEventHandler), null, eventHandler.Method); 29 | 30 | _mHandler = Invoke; 31 | _mUnregister = unregister; 32 | } 33 | 34 | /// 35 | /// Invokes the event 36 | /// 37 | /// 38 | /// 39 | public void Invoke(object? sender, TE e) 40 | { 41 | T target = (T)_mTargetRef.Target!; 42 | 43 | if (sender != null) _mOpenHandler.Invoke(target, sender, e); 44 | } 45 | 46 | /// 47 | /// The event handler 48 | /// 49 | public EventHandler Handler 50 | { 51 | get { return _mHandler; } 52 | } 53 | 54 | /// 55 | /// The implicit operator 56 | /// 57 | /// 58 | /// 59 | public static implicit operator EventHandler(WeakEventHandler weh) 60 | { 61 | return weh._mHandler; 62 | } 63 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Views/DialogWindow.axaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Helpers/CommonFiltersExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Platform.Storage; 2 | 3 | namespace JamSoft.AvaloniaUI.Dialogs.Helpers; 4 | 5 | /// 6 | /// A class containing extension methods for to allow for easier merging of file types. 7 | /// 8 | public static class CommonFiltersExtensionMethods 9 | { 10 | /// 11 | /// Merges the specified file type with the other file types. 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | public static FilePickerFileType MergeWith(this FilePickerFileType fileType, FilePickerFileType[] others, string? name) 18 | { 19 | if (!string.IsNullOrWhiteSpace(name)) 20 | { 21 | for(int i = 0;i< others.Length;i++) 22 | { 23 | if (i < others.Length - 1) 24 | { 25 | fileType.MergeWith(others[i], name); 26 | } 27 | else 28 | { 29 | fileType.MergeWith(others[i]); 30 | } 31 | } 32 | } 33 | 34 | foreach (var ft in others) 35 | { 36 | fileType.MergeWith(ft); 37 | } 38 | 39 | return fileType; 40 | } 41 | 42 | /// 43 | /// merges the specified file type with the other file type. 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | public static FilePickerFileType MergeWith(this FilePickerFileType fileType, FilePickerFileType? other, string? name = null) 50 | { 51 | if (other == null) 52 | return fileType; 53 | 54 | if (fileType.Patterns != null) 55 | { 56 | if (other.Patterns != null) 57 | { 58 | fileType.Patterns = fileType.Patterns.Concat(other.Patterns).ToArray(); 59 | } 60 | } 61 | else 62 | { 63 | fileType.Patterns = other.Patterns; 64 | } 65 | 66 | if (fileType.AppleUniformTypeIdentifiers != null) 67 | { 68 | if (other.AppleUniformTypeIdentifiers != null) 69 | { 70 | fileType.AppleUniformTypeIdentifiers = fileType.AppleUniformTypeIdentifiers.Concat(other.AppleUniformTypeIdentifiers).ToArray(); 71 | } 72 | } 73 | else 74 | { 75 | fileType.AppleUniformTypeIdentifiers = other.AppleUniformTypeIdentifiers; 76 | } 77 | 78 | if (fileType.MimeTypes != null) 79 | { 80 | if (other.MimeTypes != null) 81 | { 82 | fileType.MimeTypes = fileType.MimeTypes.Concat(other.MimeTypes).ToArray(); 83 | } 84 | } 85 | else 86 | { 87 | fileType.MimeTypes = other.MimeTypes; 88 | } 89 | 90 | if (!string.IsNullOrWhiteSpace(name)) 91 | { 92 | return new FilePickerFileType(name) 93 | { 94 | Patterns = fileType.Patterns, 95 | AppleUniformTypeIdentifiers = fileType.AppleUniformTypeIdentifiers, 96 | MimeTypes = fileType.MimeTypes 97 | }; 98 | } 99 | 100 | return fileType; 101 | } 102 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Themes/ChildStyle.axaml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 13 | 14 | 43 | 44 | 47 | 48 | 52 | 53 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Views/ChildWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Input; 4 | using Avalonia.Markup.Xaml; 5 | using Avalonia.Reactive; 6 | using JamSoft.AvaloniaUI.Dialogs.Events; 7 | using JamSoft.AvaloniaUI.Dialogs.ViewModels; 8 | 9 | namespace JamSoft.AvaloniaUI.Dialogs.Views; 10 | 11 | /// 12 | /// The default child window 13 | /// 14 | public partial class ChildWindow : Window 15 | { 16 | private bool _isClosed; 17 | 18 | private IChildWindowViewModel? _vm; 19 | 20 | /// 21 | /// The default constructor 22 | /// 23 | public ChildWindow() 24 | { 25 | InitializeComponent(); 26 | #if DEBUG 27 | this.AttachDevTools(); 28 | #endif 29 | this.FindControl("ChromeDockPanel")!.PointerPressed += OnChromePointerPressed; 30 | this.FindControl("Host")!.DataContextChanged += DialogPresenterDataContextChanged; 31 | Closed += ChildWindowClosed; 32 | PositionChanged += OnPositionChanged; 33 | } 34 | 35 | private void OnPositionChanged(object? sender, PixelPointEventArgs e) 36 | { 37 | if (_vm == null) return; 38 | 39 | _vm.RequestedLeft = e.Point.X; 40 | _vm.RequestedTop = e.Point.Y; 41 | } 42 | 43 | private void OnChromePointerPressed(object? sender, PointerPressedEventArgs e) 44 | { 45 | if (_vm == null) return; 46 | 47 | var p = e.GetCurrentPoint(null); 48 | if (p.Properties.IsLeftButtonPressed) 49 | { 50 | this.GetObservable(ClientSizeProperty).Subscribe(new AnonymousObserver((_)=> 51 | { 52 | _vm.RequestedLeft = Position.X; 53 | _vm.RequestedTop = Position.Y; 54 | })); 55 | 56 | BeginMoveDrag(e); 57 | e.Handled = false; 58 | } 59 | } 60 | 61 | void ChildWindowClosed(object? sender, EventArgs e) 62 | { 63 | PointerPressed -= OnChromePointerPressed; 64 | PositionChanged -= OnPositionChanged; 65 | Closed -= ChildWindowClosed; 66 | _isClosed = true; 67 | } 68 | 69 | private void DialogPresenterDataContextChanged(object? sender, EventArgs e) 70 | { 71 | _vm = DataContext as IChildWindowViewModel; 72 | var d = DataContext as IDialogResultVmHelper; 73 | var windowPositionAware = DataContext as IWindowPositionAware; 74 | 75 | if (d == null) 76 | { 77 | return; 78 | } 79 | 80 | d.RequestCloseDialog += new EventHandler(DialogResultTrueEvent) 81 | .MakeWeak(eh => d.RequestCloseDialog -= eh); 82 | 83 | if (windowPositionAware == null) return; 84 | 85 | Position = new PixelPoint( 86 | Convert.ToInt32(windowPositionAware.RequestedLeft), 87 | Convert.ToInt32(windowPositionAware.RequestedTop)); 88 | } 89 | 90 | private void InitializeComponent() 91 | { 92 | AvaloniaXamlLoader.Load(this); 93 | } 94 | 95 | private void DialogResultTrueEvent(object? sender, RequestCloseDialogEventArgs e) 96 | { 97 | // Important: Do not set DialogResult for a closed window 98 | // GC clears windows anyway and with MakeWeak it 99 | // closes out with IDialogResultVMHelper 100 | if (_isClosed) 101 | { 102 | return; 103 | } 104 | 105 | Close(); 106 | } 107 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs.Sample/ViewModels/MyWizardViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using JamSoft.AvaloniaUI.Dialogs.ViewModels; 3 | 4 | namespace JamSoft.AvaloniaUI.Dialogs.Sample.ViewModels; 5 | 6 | public class MyWizardViewModel : WizardViewModel 7 | { 8 | private string? _valueOne; 9 | private string? _valueTwo; 10 | private string? _valueThree; 11 | private string? _valueFour; 12 | private bool _wizardStepOneComplete; 13 | private bool _wizardStepTwoComplete; 14 | private bool _wizardStepThreeComplete; 15 | private bool _wizardStepFourComplete; 16 | private ObservableCollection? _comboboxItems; 17 | private ComboBoxItemViewModel? _selectedItem; 18 | 19 | public MyWizardViewModel() 20 | { 21 | ComboboxItems = new ObservableCollection 22 | { 23 | new ComboBoxItemViewModel { Name = string.Empty, Value = null }, 24 | new ComboBoxItemViewModel { Name = "Item One", Value = 1 }, 25 | new ComboBoxItemViewModel { Name = "Item Two", Value = 2 }, 26 | new ComboBoxItemViewModel { Name = "Item Three", Value = 3 } 27 | }; 28 | } 29 | 30 | public ObservableCollection? ComboboxItems 31 | { 32 | get => _comboboxItems; 33 | set => RaiseAndSetIfChanged(ref _comboboxItems, value); 34 | } 35 | 36 | public ComboBoxItemViewModel? SelectedItem 37 | { 38 | get => _selectedItem; 39 | set 40 | { 41 | RaiseAndSetIfChanged(ref _selectedItem, value); 42 | WizardStepOneComplete = !string.IsNullOrWhiteSpace(ValueOne) && value?.Value != null; 43 | } 44 | } 45 | 46 | public string? ValueOne 47 | { 48 | get => _valueOne; 49 | set 50 | { 51 | RaiseAndSetIfChanged(ref _valueOne, value); 52 | WizardStepOneComplete = !string.IsNullOrWhiteSpace(value) && SelectedItem?.Value != null; 53 | } 54 | } 55 | 56 | public string? ValueTwo 57 | { 58 | get => _valueTwo; 59 | set 60 | { 61 | RaiseAndSetIfChanged(ref _valueTwo, value); 62 | WizardStepTwoComplete = !string.IsNullOrWhiteSpace(value); 63 | } 64 | } 65 | 66 | public string? ValueThree 67 | { 68 | get => _valueThree; 69 | set 70 | { 71 | RaiseAndSetIfChanged(ref _valueThree, value); 72 | WizardStepThreeComplete = !string.IsNullOrWhiteSpace(value); 73 | } 74 | } 75 | 76 | public string? ValueFour 77 | { 78 | get => _valueFour; 79 | set 80 | { 81 | RaiseAndSetIfChanged(ref _valueFour, value); 82 | WizardStepFourComplete = !string.IsNullOrWhiteSpace(value); 83 | } 84 | } 85 | 86 | public bool WizardStepOneComplete 87 | { 88 | get => _wizardStepOneComplete; 89 | set => RaiseAndSetIfChanged(ref _wizardStepOneComplete, value); 90 | } 91 | 92 | public bool WizardStepTwoComplete 93 | { 94 | get => _wizardStepTwoComplete; 95 | set => RaiseAndSetIfChanged(ref _wizardStepTwoComplete, value); 96 | } 97 | 98 | public bool WizardStepThreeComplete 99 | { 100 | get => _wizardStepThreeComplete; 101 | set => RaiseAndSetIfChanged(ref _wizardStepThreeComplete, value); 102 | } 103 | 104 | public bool WizardStepFourComplete 105 | { 106 | get => _wizardStepFourComplete; 107 | set => RaiseAndSetIfChanged(ref _wizardStepFourComplete, value); 108 | } 109 | } -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Themes/WizardStyle.axaml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 0 0 0 2 23 | 24 | 25 | 65 | 66 | 69 | 70 | 73 | 74 | 77 | 78 | 81 | 82 | 85 | 86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /src/JamSoft.AvaloniaUI.Dialogs/Views/MsgBoxWindow.axaml: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |