├── .XamlStyler
├── .editorconfig
├── .gitattributes
├── .github
└── dependabot.yml
├── .gitignore
├── .vscode
├── launch.json
└── tasks.json
├── .vsconfig
├── Directory.Packages.props
├── LICENSE.md
├── MvvmScarletToolkit.ruleset
├── MvvmScarletToolkit.sln
├── MvvmScarletToolkit.slnf
├── README.md
├── build.config
├── build.ps1
├── cake
├── Build.csproj
├── Build.sln
├── BuildContext.cs
├── BuildLifetime.cs
├── Program.cs
├── Tasks
│ ├── BuildAndPack.cs
│ ├── CleanSolution.cs
│ ├── CleanSolutionAgain.cs
│ ├── CoberturaReport.cs
│ ├── ConvertCoverage.cs
│ ├── Default.cs
│ ├── HtmlReport.cs
│ ├── PushGithub.cs
│ ├── PushLocally.cs
│ ├── PushNuget.cs
│ ├── Test.cs
│ ├── TestAndUploadReport.cs
│ ├── UpdateAssemblyInfo.cs
│ └── UploadCodecovReport.cs
└── Utils.cs
├── codecov.yml
├── global.json
├── nuget.config
├── src
├── Directory.Build.props
├── Directory.Build.targets
├── MvvmScarletToolkit.Abstractions
│ ├── AbstractBuilder.cs
│ ├── IAsyncCommand.cs
│ ├── IBuilder.cs
│ ├── IBusinessViewModelListBase.cs
│ ├── IBusyStack.cs
│ ├── ICancelCommand.cs
│ ├── IChangeTracker.cs
│ ├── IConcurrentCommand.cs
│ ├── IExitService.cs
│ ├── ILocalizationProvider.cs
│ ├── ILocalizationService.cs
│ ├── ILocalizationViewModel.cs
│ ├── IObservableBusyStack.cs
│ ├── IScarletCommandManager.cs
│ ├── IScarletDispatcher.cs
│ ├── IScarletEventManager.cs
│ ├── IScarletExceptionHandler.cs
│ ├── IToolkitChangeTracker.cs
│ ├── IVirtualizationViewModel.cs
│ ├── MvvmScarletToolkit.Abstractions.csproj
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── readme.md
├── MvvmScarletToolkit.Avalonia
│ ├── Implementations
│ │ ├── ScarletCommandBuilder.cs
│ │ ├── ScarletCommandManager.cs
│ │ ├── ScarletDispatcher.cs
│ │ ├── ScarletExitService.cs
│ │ ├── ScarletLocalizationProvider.cs
│ │ ├── ScarletWeakEventManager.cs
│ │ └── WeakEventManager.cs
│ └── MvvmScarletToolkit.Avalonia.csproj
├── MvvmScarletToolkit.Commands
│ ├── CommandBuilderContext.cs
│ ├── CommandBuilderContextExtensions.cs
│ ├── CommandBuilderExtensions.cs
│ ├── Core
│ │ ├── CancelCommand.cs
│ │ ├── ConcurrentCancelCommand.cs
│ │ ├── ConcurrentCommand.cs
│ │ ├── ConcurrentCommandBase.cs
│ │ ├── ConcurrentCommandDecoratorBase.cs
│ │ ├── GenericConcurrentCommandBase.cs
│ │ ├── IgnoreExceptionHandler.cs
│ │ ├── NoCancellationCommand.cs
│ │ ├── NotifyTaskCompletion.cs
│ │ └── SequentialAsyncCommandDecorator.cs
│ ├── IScarletCommandBuilder.cs
│ ├── MvvmScarletToolkit.Commands.csproj
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── readme.md
├── MvvmScarletToolkit.Incubator
│ ├── BoolDialogResultViewModel.cs
│ ├── DialogResultViewModel.cs
│ ├── DialogResultViewModel_generic.cs
│ ├── ImageLoading
│ │ └── SharedBitmapSource.cs
│ ├── MvvmScarletToolkit.Incubator.csproj
│ └── Properties
│ │ └── AssemblyInfo.cs
├── MvvmScarletToolkit.Observables.Tests
│ ├── AttributedBroadCastViewModel.cs
│ ├── BroadCastViewModel.cs
│ ├── ITestViewModel.cs
│ ├── MvvmScarletToolkit.Observables.Tests.csproj
│ ├── NotifyProperyChangedTrackerTests.cs
│ ├── ObservableDictionaryTests.cs
│ ├── PropertyChangedMessageTrackerTests.cs
│ └── ViewModel.cs
├── MvvmScarletToolkit.Observables
│ ├── DispatcherProgress.cs
│ ├── Extensions
│ │ └── ObservableCollectionExtensions.cs
│ ├── IChange.cs
│ ├── MvvmScarletToolkit.Observables.csproj
│ ├── NotifyProperyChangedTracker.cs
│ ├── ObservableCircularBuffer.cs
│ ├── ObservableDictionary.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── PropertyChangedMessageTracker.cs
│ ├── ViewModels
│ │ ├── Base
│ │ │ ├── BusinessViewModelBase.cs
│ │ │ ├── BusinessViewModelBase_generic.cs
│ │ │ ├── BusinessViewModelListBase.cs
│ │ │ ├── DomainViewModelListBase.cs
│ │ │ ├── Messages
│ │ │ │ ├── ViewModelListBaseSelectionChanged.cs
│ │ │ │ ├── ViewModelListBaseSelectionChanging.cs
│ │ │ │ └── ViewModelListBaseSelectionsChanged.cs
│ │ │ ├── Rx
│ │ │ │ ├── BusinessSourceListViewModelBase.cs
│ │ │ │ ├── INotifyRefreshRequired.cs
│ │ │ │ ├── NotifyRefreshRequiredAdapter.cs
│ │ │ │ ├── SourceListViewModelBase.cs
│ │ │ │ └── VariableThresholdObservableCollectionAdaptor.cs
│ │ │ ├── ViewModelBase.cs
│ │ │ ├── ViewModelBase_generic.cs
│ │ │ └── ViewModelListBase.cs
│ │ ├── EnumViewModel.cs
│ │ ├── EnumViewModel_generic.cs
│ │ ├── Localization
│ │ │ ├── LocalizationViewModel.cs
│ │ │ ├── LocalizationsViewModel.cs
│ │ │ ├── ServiceExtensions.cs
│ │ │ └── samples.md
│ │ ├── Navigation
│ │ │ ├── Scene.cs
│ │ │ ├── Scenes.cs
│ │ │ └── samples.md
│ │ ├── Paging
│ │ │ ├── IPagedDataProvider.cs
│ │ │ └── PagedSourceListViewModelBase.cs
│ │ ├── PagingViewModel.cs
│ │ ├── State
│ │ │ ├── BusyStack.cs
│ │ │ ├── BusyToken.cs
│ │ │ ├── DisposalToken.cs
│ │ │ ├── ObservableBusyStack.cs
│ │ │ └── samples.md
│ │ ├── VersionViewModel.cs
│ │ └── ViewModelContainer.cs
│ └── readme.md
├── MvvmScarletToolkit.Wpf.Samples
│ ├── App.config
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── Controls
│ │ ├── DragAndDrop.xaml
│ │ └── DragAndDrop.xaml.cs
│ ├── Features
│ │ ├── AsyncState
│ │ │ ├── AsyncStateListViewModel.cs
│ │ │ └── AsyncStateViewModel.cs
│ │ ├── Busy
│ │ │ ├── BusyViewModel.cs
│ │ │ └── ObservableBusyViewModel.cs
│ │ ├── ContextMenu
│ │ │ ├── ContextMenuViewModel.cs
│ │ │ └── ContextMenuViewModels.cs
│ │ ├── DataGrid
│ │ │ ├── DataGridDataProvider.cs
│ │ │ ├── DataGridRowViewModel.cs
│ │ │ └── DataGridViewModel.cs
│ │ ├── DialogViewModel.cs
│ │ ├── Enums
│ │ │ ├── EnumViewModel.cs
│ │ │ └── ViewModelEnum.cs
│ │ ├── FormViewModel.cs
│ │ ├── Geometry
│ │ │ ├── GeometryContainer.cs
│ │ │ └── GeometryRenderViewModel.cs
│ │ ├── Image
│ │ │ ├── Image.cs
│ │ │ ├── ImageFactory.cs
│ │ │ └── Images.cs
│ │ ├── NavigationViewModel.cs
│ │ ├── ObservableDictionaryViewModel.cs
│ │ ├── PasswordViewModel.cs
│ │ ├── Process
│ │ │ ├── ProcessData.cs
│ │ │ ├── ProcessErrorData.cs
│ │ │ ├── ProcessViewModel.cs
│ │ │ └── ProcessingImagesViewModel.cs
│ │ ├── ProgressViewModel.cs
│ │ ├── ToastsViewmodel.cs
│ │ └── Virtualization
│ │ │ ├── DataEntriesViewModel.cs
│ │ │ └── DataEntryViewModel.cs
│ ├── MainWindow.xaml
│ ├── MainWindow.xaml.cs
│ ├── MvvmScarletToolkit.Wpf.Samples.csproj
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── PublishProfiles
│ │ │ └── FolderProfile.pubxml
│ └── Resources
│ │ ├── Death_to_Stock_Photography_RideorDie_8.jpg
│ │ ├── Moon_Color_Hypersaturated_Stars_900.jpg
│ │ ├── wallhaven-245035.jpg
│ │ ├── wallhaven-319605.jpg
│ │ ├── wallhaven-401406.jpg
│ │ └── wallhaven-75354.jpg
├── MvvmScarletToolkit.Wpf.Tests
│ ├── AllowableCharactersTextBoxBehaviorServiceTests.cs
│ ├── CommandBuilderContextTests.cs
│ ├── CommandBuilderExtensionTests.cs
│ ├── ConcurrentCommandTests.cs
│ ├── IsNotNullOrEmptyTests.cs
│ ├── IsNotNullOrWhiteSpaceTests.cs
│ ├── IsNotNullTests.cs
│ ├── IsNotTests.cs
│ ├── IsNullOrEmptyTests.cs
│ ├── IsNullOrWhiteSpaceTests.cs
│ ├── IsNullTests.cs
│ ├── MvvmScarletToolkit.Wpf.Tests.csproj
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── ScarletCommandBuilderTests.cs
│ ├── TestData
│ │ ├── DerivedObjectViewModelBase.cs
│ │ ├── DerivedViewModelBase.cs
│ │ └── DerivedViewModelListBase.cs
│ ├── Util
│ │ ├── TestDispatcher.cs
│ │ └── Utils.cs
│ ├── ViewModelBaseTests.cs
│ └── ViewModelListBaseTests.cs
├── MvvmScarletToolkit.Wpf
│ ├── Attached Properties
│ │ ├── Filter.cs
│ │ └── Focus.cs
│ ├── Behaviors
│ │ ├── AllowableCharactersTextBoxBehavior.cs
│ │ ├── AllowableCharactersTextBoxBehaviorService.cs
│ │ ├── AutoRepositionPopupBehavior.cs
│ │ ├── AutoScrollBehavior.cs
│ │ ├── LaunchNavigateUriAsNewProcessBehavior.cs
│ │ ├── MultiListBoxSelectionBehavior.cs
│ │ ├── MultiSelectionBehavior.cs
│ │ ├── PasswordBindingBehavior.cs
│ │ ├── ScrollSelectionIntoViewBehavior.cs
│ │ ├── ScrollToEndCommandBehavior.cs
│ │ ├── SelectedTreeViewItemBehavior.cs
│ │ ├── SmoothProgressBehavior.cs
│ │ └── WatermarkBehavior.cs
│ ├── BindingProxy.cs
│ ├── Extensions
│ │ └── DependencyObjectExtensions.cs
│ ├── Features
│ │ ├── DataTemplateSelectionManagement
│ │ │ ├── DataTemplateCollection.cs
│ │ │ └── TypeDataTemplateSelector.cs
│ │ ├── FileSystemBrowser
│ │ │ ├── FileExtensions.cs
│ │ │ ├── FileSystemBrowser.cs
│ │ │ ├── FileSystemViewModelFactory.cs
│ │ │ ├── FileSystemViewModelFactoryExtensions.cs
│ │ │ ├── Generic.xaml
│ │ │ ├── Interfaces
│ │ │ │ ├── IFileSystemChild.cs
│ │ │ │ ├── IFileSystemDirectory.cs
│ │ │ │ ├── IFileSystemDrive.cs
│ │ │ │ ├── IFileSystemFile.cs
│ │ │ │ ├── IFileSystemInfo.cs
│ │ │ │ ├── IFileSystemParent.cs
│ │ │ │ ├── IFileSystemViewModelFactory.cs
│ │ │ │ └── IMimeTypeResolver.cs
│ │ │ ├── MimeTypeResolvers
│ │ │ │ ├── MagicNumberMimeTypeResolver.cs
│ │ │ │ ├── RegistryFileExtensionMimeTypeResolver.cs
│ │ │ │ ├── StaticFileExtensionMimeTypeResolver.cs
│ │ │ │ └── UrlMonMimeTypeResolver.cs
│ │ │ ├── ViewModels
│ │ │ │ ├── FileSystemOptionsViewModel.cs
│ │ │ │ ├── FileSystemViewModel.cs
│ │ │ │ ├── ScarletDirectory.cs
│ │ │ │ ├── ScarletDrive.cs
│ │ │ │ └── ScarletFile.cs
│ │ │ └── readme.md
│ │ ├── GridViewColumnSizing
│ │ │ ├── FixedColumn.cs
│ │ │ ├── LayoutColumn.cs
│ │ │ ├── ListViewLayoutManager.cs
│ │ │ ├── ProportionalColumn.cs
│ │ │ └── RangeColumn.cs
│ │ ├── GroupManagement
│ │ │ ├── GroupViewModel.cs
│ │ │ ├── GroupingViewModel.cs
│ │ │ ├── GroupsViewModel.cs
│ │ │ └── GroupsViewModelRemoved.cs
│ │ ├── HtmlTextBlock
│ │ │ ├── Enums
│ │ │ │ ├── CharType.cs
│ │ │ │ ├── HTMLFlag.cs
│ │ │ │ └── SymbolType.cs
│ │ │ ├── HtmlAttributeStringSerializer.cs
│ │ │ ├── HtmlHighlightTextBlock.cs
│ │ │ ├── HtmlParser.cs
│ │ │ ├── HtmlTextBlock.cs
│ │ │ ├── InlineCreationContext.cs
│ │ │ ├── Interfaces
│ │ │ │ ├── IParamParser.cs
│ │ │ │ └── IPropertySerializer.cs
│ │ │ ├── Models
│ │ │ │ ├── HTMLTagInfo.cs
│ │ │ │ ├── HtmlTag.cs
│ │ │ │ ├── HtmlTagNode.cs
│ │ │ │ └── HtmlTagTree.cs
│ │ │ └── ParamParser.cs
│ │ ├── ToastNotification
│ │ │ ├── Generic.xaml
│ │ │ ├── IToast.cs
│ │ │ ├── IToastService.cs
│ │ │ ├── ToastService.cs
│ │ │ ├── ToastServiceConfiguration.cs
│ │ │ ├── ToastServiceExtensions.cs
│ │ │ ├── ToastType.cs
│ │ │ └── ToastViewModel.cs
│ │ ├── VirtualizingTilePanel.cs
│ │ └── VirtualizingWrapPanel.cs
│ ├── Implementations
│ │ ├── ScarletCommandBuilder.cs
│ │ ├── ScarletCommandManager.cs
│ │ ├── ScarletDispatcher.cs
│ │ ├── ScarletExitService.cs
│ │ ├── ScarletLocalizationProvider.cs
│ │ └── ScarletWeakEventManager.cs
│ ├── MarkupExtensions
│ │ ├── ConverterMarkupExtension.cs
│ │ ├── Converters
│ │ │ ├── DebugConverter.cs
│ │ │ ├── Flatten.cs
│ │ │ ├── GreaterThan.cs
│ │ │ ├── IgnoreNullOrEmptyStrings.cs
│ │ │ ├── InvertBooleanToVisibilityConverter.cs
│ │ │ ├── IsNot.cs
│ │ │ ├── IsNotNull.cs
│ │ │ ├── IsNotNullOrEmpty.cs
│ │ │ ├── IsNotNullOrWhiteSpace.cs
│ │ │ ├── IsNull.cs
│ │ │ ├── IsNullOrEmpty.cs
│ │ │ ├── IsNullOrWhiteSpace.cs
│ │ │ ├── MultiBooleanAndConverter.cs
│ │ │ ├── RadioButtonCheckedConverter.cs
│ │ │ ├── SmallerThan.cs
│ │ │ └── ToCase.cs
│ │ ├── EnumBindingSourceExtension.cs
│ │ ├── MultiConverterMarkupExtension.cs
│ │ └── StartProcessExtension.cs
│ ├── MvvmScarletToolkit.Wpf.csproj
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── TriggerActions
│ │ ├── ClearPasswordBoxAction.cs
│ │ └── ClearTextBoxAction.cs
│ └── readme.md
├── MvvmScarletToolkit
│ ├── Extensions
│ │ ├── CommandExtensions.cs
│ │ ├── DispatcherExtensions.cs
│ │ ├── EnumExtensions.cs
│ │ ├── EnumerableExtensions.cs
│ │ ├── EventExtension.cs
│ │ ├── ListExtensions.cs
│ │ ├── ObservableCollectionExtensions.cs
│ │ ├── QueryExtensions.cs
│ │ └── TypeExtensions.cs
│ ├── Messages
│ │ └── CancellableGenericScarletMessage.cs
│ ├── MvvmScarletToolkit.csproj
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── readme.md
└── SharedAssemblyInfo.cs
└── version.json
/.XamlStyler:
--------------------------------------------------------------------------------
1 | {
2 | "AttributesTolerance": 2,
3 | "KeepFirstAttributeOnSameLine": true,
4 | "MaxAttributeCharatersPerLine": 0,
5 | "MaxAttributesPerLine": 1,
6 | "NewlineExemptionElements": "RadialGradientBrush, GradientStop, LinearGradientBrush, ScaleTransfom, SkewTransform, RotateTransform, TranslateTransform, Trigger, Condition, Setter",
7 | "SeparateByGroups": false,
8 | "AttributeIndentation": 0,
9 | "AttributeIndentationStyle": 1,
10 | "RemoveDesignTimeReferences": false,
11 | "EnableAttributeReordering": true,
12 | "AttributeOrderingRuleGroups": [
13 | "x:Class",
14 | "xmlns, xmlns:x",
15 | "xmlns:*",
16 | "x:Key, Key, x:Name, Name, x:Uid, Uid, Title",
17 | "Grid.Row, Grid.RowSpan, Grid.Column, Grid.ColumnSpan, Canvas.Left, Canvas.Top, Canvas.Right, Canvas.Bottom",
18 | "Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight",
19 | "Margin, Padding, HorizontalAlignment, VerticalAlignment, HorizontalContentAlignment, VerticalContentAlignment, Panel.ZIndex",
20 | "*:*, *",
21 | "PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint",
22 | "mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText",
23 | "options:Freeze, op:Freeze, o:Freeze, mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText",
24 | "Storyboard.*, From, To, Duration"
25 | ],
26 | "FirstLineAttributes": "",
27 | "OrderAttributesByName": true,
28 | "PutEndingBracketOnNewLine": false,
29 | "RemoveEndingTagOfEmptyElement": true,
30 | "SpaceBeforeClosingSlash": true,
31 | "RootElementLineBreakRule": 0,
32 | "ReorderVSM": 2,
33 | "ReorderGridChildren": true,
34 | "ReorderCanvasChildren": false,
35 | "ReorderSetters": 1,
36 | "FormatMarkupExtension": true,
37 | "NoNewLineMarkupExtensions": "x:Bind, Binding",
38 | "ThicknessSeparator": 1,
39 | "ThicknessAttributes": "Margin, Padding, BorderThickness, ThumbnailClipMargin",
40 | "FormatOnSave": false,
41 | "CommentPadding": 2,
42 | }
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: nuget
4 | directory: "/"
5 | schedule:
6 | interval: weekly
7 | time: "04:00"
8 | open-pull-requests-limit: 10
9 | target-branch: dev
10 | ignore:
11 | - dependency-name: Magick.NET.SystemWindowsMedia
12 | versions:
13 | - 3.0.5
14 | - 3.0.6
15 | - dependency-name: Magick.NET-Q8-AnyCPU
16 | versions:
17 | - 7.23.1
18 | - 7.23.2
19 | - dependency-name: IDisposableAnalyzers
20 | versions:
21 | - 3.4.10
22 | - dependency-name: FluentValidation
23 | versions:
24 | - 9.4.0
25 | - 9.5.0
26 | - dependency-name: Moq
27 | versions:
28 | - 4.16.0
29 | - dependency-name: nunit
30 | versions:
31 | - 3.13.0
32 | - dependency-name: Microsoft.Xaml.Behaviors.Wpf
33 | versions:
34 | - 1.1.31
35 | - dependency-name: WpfAnalyzers
36 | versions:
37 | - 3.5.4
38 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to find out which attributes exist for C# debugging
3 | // Use hover for the description of the existing attributes
4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": ".NET Core Launch (WpfApp)",
9 | "type": "coreclr",
10 | "request": "launch",
11 | "preLaunchTask": "build",
12 | // If you have changed target frameworks, make sure to update the program path.
13 | "program": "${workspaceFolder}/DemoApp/bin/Debug/netcoreapp3.1/win10-x64/DemoApp.exe",
14 | "args": [],
15 | "externalConsole": true,
16 | "cwd": "${workspaceFolder}/DemoApp",
17 | // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
18 | "console": "internalConsole",
19 | "stopAtEntry": false
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "build",
6 | "command": "dotnet",
7 | "type": "process",
8 | "args": [
9 | "build",
10 | "${workspaceFolder}/DemoApp/DemoApp.csproj",
11 | "/property:GenerateFullPaths=true",
12 | "/consoleloggerparameters:NoSummary"
13 | ],
14 | "problemMatcher": "$msCompile"
15 | },
16 | {
17 | "label": "publish",
18 | "command": "dotnet",
19 | "type": "process",
20 | "args": [
21 | "publish",
22 | "${workspaceFolder}/DemoApp/DemoApp.csproj",
23 | "/property:GenerateFullPaths=true",
24 | "/consoleloggerparameters:NoSummary"
25 | ],
26 | "problemMatcher": "$msCompile"
27 | },
28 | {
29 | "label": "watch",
30 | "command": "dotnet",
31 | "type": "process",
32 | "args": [
33 | "watch",
34 | "run",
35 | "${workspaceFolder}/DemoApp/DemoApp.csproj",
36 | "/property:GenerateFullPaths=true",
37 | "/consoleloggerparameters:NoSummary"
38 | ],
39 | "problemMatcher": "$msCompile"
40 | }
41 | ]
42 | }
--------------------------------------------------------------------------------
/.vsconfig:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0",
3 | "components": [
4 | "Microsoft.VisualStudio.Component.CoreEditor",
5 | "Microsoft.VisualStudio.Workload.CoreEditor",
6 | "Microsoft.NetCore.Component.SDK",
7 | "Microsoft.VisualStudio.Component.NuGet",
8 | "Microsoft.VisualStudio.Component.Roslyn.Compiler",
9 | "Microsoft.VisualStudio.Component.Roslyn.LanguageServices",
10 | "Microsoft.NetCore.Component.DevelopmentTools",
11 | "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites",
12 | "Microsoft.Component.MSBuild",
13 | "Microsoft.VisualStudio.Component.TextTemplating",
14 | "Microsoft.VisualStudio.Component.ManagedDesktop.Core",
15 | "Microsoft.VisualStudio.Component.IntelliCode",
16 | "Microsoft.VisualStudio.Component.Debugger.JustInTime",
17 | "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites",
18 | "Microsoft.VisualStudio.Workload.ManagedDesktop"
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024
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 |
--------------------------------------------------------------------------------
/MvvmScarletToolkit.ruleset:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/MvvmScarletToolkit.slnf:
--------------------------------------------------------------------------------
1 | {
2 | "solution": {
3 | "path": "MvvmScarletToolkit.sln",
4 | "projects": [
5 | "src\\MvvmScarletToolkit.Abstractions\\MvvmScarletToolkit.Abstractions.csproj",
6 | "src\\MvvmScarletToolkit.Commands\\MvvmScarletToolkit.Commands.csproj",
7 | "src\\MvvmScarletToolkit.Observables\\MvvmScarletToolkit.Observables.csproj",
8 | "src\\MvvmScarletToolkit.Wpf\\MvvmScarletToolkit.Wpf.csproj",
9 | "src\\MvvmScarletToolkit.Xamarin.Forms\\MvvmScarletToolkit.Xamarin.Forms.csproj",
10 | "src\\MvvmScarletToolkit\\MvvmScarletToolkit.csproj"
11 | ]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/build.config:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | DOTNET_VERSION=7.0.102
3 |
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | dotnet run --project cake/Build.csproj -- $args
2 | exit $LASTEXITCODE;
3 |
--------------------------------------------------------------------------------
/cake/Build.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net9.0
5 | true
6 |
7 |
8 | $(MSBuildProjectDirectory)
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | all
19 | runtime; build; native; contentfiles; analyzers; buildtransitive
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/cake/Build.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31025.194
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Build", "Build.csproj", "{79BD7F6E-3F66-4597-99B9-6207D04DEB69}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {79BD7F6E-3F66-4597-99B9-6207D04DEB69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {79BD7F6E-3F66-4597-99B9-6207D04DEB69}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {79BD7F6E-3F66-4597-99B9-6207D04DEB69}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {79BD7F6E-3F66-4597-99B9-6207D04DEB69}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {FC9F05C6-BBA9-4B34-BCD1-3FDE3469CE81}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/cake/BuildLifetime.cs:
--------------------------------------------------------------------------------
1 | using Cake.Common;
2 | using Cake.Common.Build;
3 | using Cake.Common.Diagnostics;
4 | using Cake.Common.Tools.GitVersion;
5 | using Cake.Core;
6 | using Cake.Frosting;
7 | using Cake.GitVersioning;
8 |
9 | namespace Build
10 | {
11 | public sealed class BuildLifetime : FrostingLifetime
12 | {
13 | public override void Setup(BuildContext context, ISetupContext info)
14 | {
15 | context.GitVersion = context.GitVersioningGetVersion();
16 | context.Branch = context.GitVersion().BranchName;
17 |
18 | context.Information("Branch: {0}", context.Branch);
19 |
20 | if (context.IsPublicRelease && context.Branch == "master")
21 | {
22 | context.Information("Building a {0} release.", "public");
23 | }
24 | else
25 | {
26 | context.Information("Building a {0}release.", "pre-");
27 | }
28 |
29 | context.Information("Provider: {0}", context.BuildSystem().Provider);
30 | context.Information("Platform: {0} ({1})", context.Environment.Platform.Family, context.Environment.Platform.Is64Bit ? "x64" : "x86");
31 |
32 | context.Information("NUGETORG_APIKEY was {0} set.", string.IsNullOrEmpty(context.EnvironmentVariable("NUGETORG_APIKEY")) ? "not" : "");
33 | context.Information("GITHUB_APIKEY was {0} set.", string.IsNullOrEmpty(context.EnvironmentVariable("GITHUB_APIKEY")) ? "not" : "");
34 | context.Information("CODECOV_TOKEN was {0} set.", string.IsNullOrEmpty(context.EnvironmentVariable("CODECOV_TOKEN")) ? "not" : "");
35 |
36 | context.Information("reportsFolder: {0}", context.ReportsPath.FullPath);
37 | context.Information("coberturaResultFile: {0}", context.CoberturaResultFile.FullPath);
38 |
39 | context.Information("dotnet tool: {0}", context.Tools.Resolve("dotnet.exe"));
40 | }
41 |
42 | public override void Teardown(BuildContext context, ITeardownContext info)
43 | {
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/cake/Program.cs:
--------------------------------------------------------------------------------
1 | using Cake.Frosting;
2 | using System;
3 |
4 | namespace Build
5 | {
6 | public static class Program
7 | {
8 | public static int Main(string[] args)
9 | {
10 | return new CakeHost()
11 | .InstallTool(new Uri("nuget:?package=Codecov&version=1.13.0"))
12 | .InstallTool(new Uri("nuget:?package=NUnit.ConsoleRunner&version=3.20.0"))
13 | .InstallTool(new Uri("nuget:?package=ReportGenerator&version=5.4.5"))
14 | .InstallTool(new Uri("nuget:?package=GitVersion.CommandLine&version=5.12.0"))
15 | .InstallTool(new Uri("nuget:?package=nuget.commandline&version=6.13.2"))
16 | .InstallTool(new Uri("nuget:?package=dotnet-coverage&version=17.13.1"))
17 | .UseContext()
18 | .UseLifetime()
19 | .UseWorkingDirectory("..")
20 | .Run(args);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/cake/Tasks/BuildAndPack.cs:
--------------------------------------------------------------------------------
1 | using Cake.Common;
2 | using Cake.Core;
3 | using Cake.Core.IO;
4 | using Cake.Frosting;
5 | using System.Linq;
6 |
7 | namespace Build
8 | {
9 | public sealed class BuildAndPack : FrostingTask
10 | {
11 | public override void Run(BuildContext context)
12 | {
13 | foreach (var project in context.NugetPackageProjects)
14 | {
15 | var semver = context.GitVersion.SemVer2;
16 | var settings = new ProcessSettings()
17 | .UseWorkingDirectory(".")
18 | .WithArguments(builder => builder
19 | .Append("pack")
20 | .AppendQuoted(project.ProjectFile.FullPath)
21 | .Append($"-c {BuildContext.BuildConfiguration}")
22 | .Append($"--output \"{context.PackagePath.FullPath}\"")
23 | .Append($"-p:PackageVersion={context.GitVersion.SemVer2}")
24 | .Append($"-p:PublicRelease={context.IsPublicRelease}") // Nerdbank.GitVersioning - omit git commit ID
25 |
26 | // Creating symbol packages
27 | .Append($"--include-symbols")
28 | .Append("--include-source")
29 | .Append($"-p:SymbolPackageFormat=snupkg")
30 |
31 | // enable source linking
32 | .Append($"-p:PublishRepositoryUrl=true")
33 |
34 | // Deterministic Builds
35 | .Append($"-p:EmbedUntrackedSources=true")
36 |
37 | .Append($"-p:DebugType=portable")
38 | .Append($"-p:DebugSymbols=true")
39 | );
40 |
41 | context.StartProcess("dotnet", settings);
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/cake/Tasks/CleanSolution.cs:
--------------------------------------------------------------------------------
1 | using Cake.Frosting;
2 |
3 | namespace Build
4 | {
5 | public sealed class CleanSolution : FrostingTask
6 | {
7 | public override void Run(BuildContext context)
8 | {
9 | context.Clean(true, true, true, true);
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/cake/Tasks/CleanSolutionAgain.cs:
--------------------------------------------------------------------------------
1 | using Cake.Frosting;
2 |
3 | namespace Build
4 | {
5 | public sealed class CleanSolutionAgain : FrostingTask
6 | {
7 | public override void Run(BuildContext context)
8 | {
9 | context.Clean(true, true, true, false);
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/cake/Tasks/CoberturaReport.cs:
--------------------------------------------------------------------------------
1 | using Cake.Common.IO;
2 | using Cake.Common.Tools.ReportGenerator;
3 | using Cake.Core;
4 | using Cake.Core.IO;
5 | using Cake.Frosting;
6 |
7 | namespace Build
8 | {
9 | [IsDependentOn(typeof(ConvertCoverage))]
10 | public sealed class CoberturaReport : FrostingTask
11 | {
12 | public override void Run(BuildContext context)
13 | {
14 | context.MergeReports("./results/coverage/**/*.xml", ReportGeneratorReportType.Cobertura, "cobertura");
15 | }
16 |
17 | public override bool ShouldRun(BuildContext context)
18 | {
19 | var files = context.GetFiles("./results/coverage/**/*.xml");
20 | return files.Count > 0;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/cake/Tasks/ConvertCoverage.cs:
--------------------------------------------------------------------------------
1 | using Cake.Common;
2 | using Cake.Common.IO;
3 | using Cake.Core;
4 | using Cake.Core.IO;
5 | using Cake.Frosting;
6 | using System.Linq;
7 |
8 | namespace Build
9 | {
10 | [IsDependentOn(typeof(Test))]
11 | public sealed class ConvertCoverage : FrostingTask
12 | {
13 | public override void Run(BuildContext context)
14 | {
15 | var dotnetExe = context.Tools.Resolve("dotnet.exe");
16 | var codeCoverageExe = context.Tools.Resolve("dotnet-coverage.dll");
17 |
18 | foreach (var file in context.GetFiles($"{context.ResultsPath.FullPath}/coverage/**/*.coverage"))
19 | {
20 | var result = System.IO.Path.ChangeExtension(file.FullPath, ".xml");
21 |
22 | var settings = new ProcessSettings()
23 | .UseWorkingDirectory(context.ResultsPath)
24 | .WithArguments(builder => builder
25 | .AppendQuoted(codeCoverageExe.FullPath)
26 | .Append("merge")
27 | .Append("--remove-input-files")
28 | .AppendSwitchQuoted(@"--output", " ", result)
29 | .AppendSwitch("--output-format", "xml")
30 | .Append(file.FullPath)
31 | );
32 |
33 | context.StartProcess(dotnetExe.FullPath, settings);
34 | }
35 | }
36 |
37 | public override bool ShouldRun(BuildContext context)
38 | {
39 | return context.Tools.Resolve("dotnet-coverage.dll") != null;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/cake/Tasks/Default.cs:
--------------------------------------------------------------------------------
1 | using Cake.Frosting;
2 |
3 | namespace Build
4 | {
5 | [IsDependentOn(typeof(CleanSolution))]
6 | [IsDependentOn(typeof(UpdateAssemblyInfo))]
7 | [IsDependentOn(typeof(TestAndUploadReport))]
8 | [IsDependentOn(typeof(CleanSolutionAgain))]
9 | [IsDependentOn(typeof(BuildAndPack))]
10 | [IsDependentOn(typeof(PushNuget))]
11 | [IsDependentOn(typeof(PushGithub))]
12 | [IsDependentOn(typeof(PushLocally))]
13 | public sealed class Default : FrostingTask;
14 | }
15 |
--------------------------------------------------------------------------------
/cake/Tasks/HtmlReport.cs:
--------------------------------------------------------------------------------
1 | using Cake.Common.IO;
2 | using Cake.Common.Tools.ReportGenerator;
3 | using Cake.Core;
4 | using Cake.Core.IO;
5 | using Cake.Frosting;
6 |
7 | namespace Build
8 | {
9 | [IsDependentOn(typeof(ConvertCoverage))]
10 | public sealed class HtmlReport : FrostingTask
11 | {
12 | public override void Run(BuildContext context)
13 | {
14 | context.MergeReports("./results/coverage/**/*.xml", ReportGeneratorReportType.Html, "html");
15 | }
16 |
17 | public override bool ShouldRun(BuildContext context)
18 | {
19 | var files = context.GetFiles("./results/coverage/**/*.xml");
20 | return files.Count > 0;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/cake/Tasks/PushGithub.cs:
--------------------------------------------------------------------------------
1 | using Cake.Common;
2 | using Cake.Common.Build;
3 | using Cake.Common.IO;
4 | using Cake.Core;
5 | using Cake.Core.IO;
6 | using Cake.Frosting;
7 |
8 | namespace Build
9 | {
10 | public sealed class PushGithub : FrostingTask
11 | {
12 | public override void Run(BuildContext context)
13 | {
14 | foreach (var package in context.GetFiles(context.PackagePath.FullPath + "/*.nupkg"))
15 | {
16 | var settings = new ProcessSettings()
17 | .UseWorkingDirectory(".")
18 | .WithArguments(builder => builder
19 | .Append("nuget push")
20 | .AppendQuoted(package.FullPath)
21 |
22 | .AppendSwitchQuotedSecret("--api-key", context.EnvironmentVariable("GITHUB_APIKEY"))
23 | .AppendSwitch("--source", "https://nuget.pkg.github.com/insire/index.json")
24 | .Append("--skip-duplicate")
25 | );
26 |
27 | context.StartProcess("dotnet", settings);
28 | }
29 | }
30 |
31 | public override bool ShouldRun(BuildContext context)
32 | {
33 | return base.ShouldRun(context)
34 | && context.BuildSystem().IsRunningOnAzurePipelines
35 | && !string.IsNullOrEmpty(context.EnvironmentVariable("GITHUB_APIKEY"))
36 | && !context.IsPublicRelease;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/cake/Tasks/PushLocally.cs:
--------------------------------------------------------------------------------
1 | using Cake.Common.Build;
2 | using Cake.Common.IO;
3 | using Cake.Common.Tools.NuGet;
4 | using Cake.Core;
5 | using Cake.Core.IO;
6 | using Cake.Frosting;
7 |
8 | namespace Build
9 | {
10 | public sealed class PushLocally : FrostingTask
11 | {
12 | private const string LocalNugetFolder = @"D:\Drop\NuGet";
13 |
14 | public override void Run(BuildContext context)
15 | {
16 | if (!context.NuGetHasSource(LocalNugetFolder))
17 | {
18 | context.NuGetAddSource("Local", LocalNugetFolder);
19 | }
20 |
21 | foreach (var package in context.GetFiles(context.PackagePath.FullPath + "/*.nupkg"))
22 | {
23 | context.NuGetPush(package, new Cake.Common.Tools.NuGet.Push.NuGetPushSettings()
24 | {
25 | Source = LocalNugetFolder,
26 | });
27 | }
28 | }
29 |
30 | public override bool ShouldRun(BuildContext context)
31 | {
32 | return base.ShouldRun(context)
33 | && context.BuildSystem().IsLocalBuild
34 | && context.DirectoryExists(LocalNugetFolder);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/cake/Tasks/PushNuget.cs:
--------------------------------------------------------------------------------
1 | using Cake.Common;
2 | using Cake.Common.Build;
3 | using Cake.Common.IO;
4 | using Cake.Common.Tools.NuGet;
5 | using Cake.Core;
6 | using Cake.Core.IO;
7 | using Cake.Frosting;
8 |
9 | namespace Build
10 | {
11 | public sealed class PushNuget : FrostingTask
12 | {
13 | public override void Run(BuildContext context)
14 | {
15 | foreach (var package in context.GetFiles(context.PackagePath.FullPath + "/*.nupkg"))
16 | {
17 | context.NuGetPush(package, new Cake.Common.Tools.NuGet.Push.NuGetPushSettings()
18 | {
19 | ApiKey = context.EnvironmentVariable("NUGETORG_APIKEY"),
20 | Source = "https://api.nuget.org/v3/index.json",
21 | SkipDuplicate = true,
22 | });
23 | }
24 | }
25 |
26 | public override bool ShouldRun(BuildContext context)
27 | {
28 | return base.ShouldRun(context)
29 | && context.BuildSystem().IsRunningOnAzurePipelines
30 | && !string.IsNullOrEmpty(context.EnvironmentVariable("NUGETORG_APIKEY"))
31 | && context.IsPublicRelease;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/cake/Tasks/Test.cs:
--------------------------------------------------------------------------------
1 | using Cake.Common.IO;
2 | using Cake.Common.Tools.DotNet;
3 | using Cake.Common.Tools.DotNet.Test;
4 | using Cake.Core;
5 | using Cake.Frosting;
6 | using System.Collections.Generic;
7 |
8 | namespace Build
9 | {
10 | public sealed class Test : FrostingTask
11 | {
12 | public override void Run(BuildContext context)
13 | {
14 | var testSettings = new DotNetTestSettings
15 | {
16 | Configuration = BuildContext.BuildConfiguration,
17 | NoBuild = false,
18 | NoRestore = false,
19 | NoLogo = false,
20 | ResultsDirectory = context.CoveragePath,
21 | Loggers = new[] { "trx" },
22 | Collectors = new[] { "Code Coverage" },
23 | EnvironmentVariables = new Dictionary() { ["Environment"] = "Test" },
24 | };
25 |
26 | var files = context.GetFiles(context.SourcePath.FullPath + "/*/*.Tests.csproj");
27 | foreach (var file in files)
28 | {
29 | context.DotNetTest(file.FullPath, testSettings);
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/cake/Tasks/TestAndUploadReport.cs:
--------------------------------------------------------------------------------
1 | using Cake.Frosting;
2 |
3 | namespace Build
4 | {
5 | [IsDependentOn(typeof(HtmlReport))]
6 | [IsDependentOn(typeof(UploadCodecovReport))]
7 | public sealed class TestAndUploadReport : FrostingTask;
8 | }
9 |
--------------------------------------------------------------------------------
/cake/Tasks/UploadCodecovReport.cs:
--------------------------------------------------------------------------------
1 | using Cake.Codecov;
2 | using Cake.Common;
3 | using Cake.Common.IO;
4 | using Cake.Frosting;
5 |
6 | namespace Build
7 | {
8 | [IsDependentOn(typeof(CoberturaReport))]
9 | public sealed class UploadCodecovReport : FrostingTask
10 | {
11 | public override void Run(BuildContext context)
12 | {
13 | var settings = new CodecovSettings()
14 | {
15 | Verbose = true,
16 | WorkingDirectory = context.CoberturaResultsPath,
17 | Files = new[] { context.CoberturaResultFile.FullPath },
18 | Token = context.EnvironmentVariable("CODECOV_TOKEN"),
19 | };
20 |
21 | context.Codecov(settings);
22 | }
23 |
24 | public override bool ShouldRun(BuildContext context)
25 | {
26 | return base.ShouldRun(context)
27 | && context.FileExists(context.CoberturaResultFile)
28 | && !string.IsNullOrEmpty(context.EnvironmentVariable("CODECOV_TOKEN"));
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | require_ci_to_pass: yes
3 |
4 | coverage:
5 | precision: 2
6 | round: down
7 | range: "70...100"
8 |
9 | parsers:
10 | gcov:
11 | branch_detection:
12 | conditional: yes
13 | loop: yes
14 | method: no
15 | macro: no
16 |
17 | comment:
18 | layout: "reach,diff,flags,tree"
19 | behavior: default
20 | require_changes: no
21 |
22 | fixes:
23 | - "./a/1/s/::"
24 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "9.0.203",
4 | "rollForward": "disable"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MvvmScarletToolkit
5 | SoftThorn
6 | Peter Vietense
7 | MIT
8 | https://github.com/Insire/MvvmScarletToolkit
9 | https://github.com/Insire/MvvmScarletToolkit
10 | git
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | False
10 | 13
11 | ..\..\MvvmScarletToolkit.ruleset
12 |
13 |
14 |
15 |
16 | all
17 | runtime; build; native; contentfiles; analyzers; buildtransitive
18 |
19 |
20 |
21 |
22 | True
23 | Full
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/AbstractBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace MvvmScarletToolkit
2 | {
3 | public abstract class AbstractBuilder : IBuilder
4 | {
5 | public static implicit operator TElement(AbstractBuilder @this)
6 | {
7 | return @this.Build();
8 | }
9 |
10 | public abstract TElement Build();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IAsyncCommand.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MvvmScarletToolkit
4 | {
5 | public interface IAsyncCommand : IConcurrentCommand, IDisposable;
6 | }
7 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace MvvmScarletToolkit
2 | {
3 | public interface IBuilder
4 | {
5 | TElement Build();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IBusinessViewModelListBase.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.ObjectModel;
2 | using System.ComponentModel;
3 |
4 | namespace MvvmScarletToolkit
5 | {
6 | public interface IBusinessViewModelListBase : IVirtualizationViewModel
7 | where TViewModel : class, INotifyPropertyChanged
8 | {
9 | ReadOnlyObservableCollection Items { get; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IBusyStack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MvvmScarletToolkit
4 | {
5 | public interface IBusyStack
6 | {
7 | ///
8 | /// Generate a disposeable token
9 | ///
10 | IDisposable GetToken();
11 |
12 | ///
13 | /// remove a token from the stack
14 | ///
15 | void Pull();
16 |
17 | ///
18 | /// add a token to the stack
19 | ///
20 | void Push();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/ICancelCommand.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Windows.Input;
4 |
5 | namespace MvvmScarletToolkit
6 | {
7 | public interface ICancelCommand : ICommand, IDisposable
8 | {
9 | CancellationToken Token { get; }
10 |
11 | void NotifyCommandFinished();
12 |
13 | void NotifyCommandStarting();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IConcurrentCommand.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Threading.Tasks;
3 | using System.Windows.Input;
4 |
5 | namespace MvvmScarletToolkit
6 | {
7 | public interface IConcurrentCommand : ICommand, INotifyPropertyChanged
8 | {
9 | Task ExecuteAsync(object parameter);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IExitService.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace MvvmScarletToolkit
4 | {
5 | public interface IExitService
6 | {
7 | Task ShutDown();
8 |
9 | void UnloadOnExit(IVirtualizationViewModel viewModel);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/ILocalizationProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Globalization;
3 |
4 | namespace MvvmScarletToolkit
5 | {
6 | public interface ILocalizationProvider
7 | {
8 | ///
9 | /// Translates the key into a localized value
10 | ///
11 | /// The key.
12 | ///
13 | string Translate(string key, CultureInfo culture);
14 |
15 | ///
16 | /// Gets the available languages.
17 | ///
18 | /// The available languages.
19 | IEnumerable Languages { get; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/ILocalizationService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Globalization;
4 |
5 | namespace MvvmScarletToolkit
6 | {
7 | public interface ILocalizationService : INotifyPropertyChanged
8 | {
9 | CultureInfo? CurrentLanguage { get; set; }
10 |
11 | ///
12 | /// Translates the key into a localized value
13 | ///
14 | /// The key.
15 | ///
16 | string Translate(string key);
17 |
18 | ///
19 | /// Gets the available languages.
20 | ///
21 | /// The available languages.
22 | IEnumerable Languages { get; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/ILocalizationViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | namespace MvvmScarletToolkit
5 | {
6 | public interface ILocalizationViewModel : INotifyPropertyChanged, IDisposable
7 | {
8 | string Value { get; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IObservableBusyStack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MvvmScarletToolkit
4 | {
5 | public interface IObservableBusyStack : IObservable, IBusyStack, IDisposable;
6 | }
7 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IScarletCommandManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MvvmScarletToolkit
4 | {
5 | public interface IScarletCommandManager
6 | {
7 | void InvalidateRequerySuggested();
8 |
9 | event EventHandler RequerySuggested;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IScarletDispatcher.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 |
5 | namespace MvvmScarletToolkit
6 | {
7 | public interface IScarletDispatcher
8 | {
9 | Task Invoke(Action action, CancellationToken token);
10 |
11 | Task Invoke(Func action, CancellationToken token);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IScarletEventManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MvvmScarletToolkit
4 | {
5 | public interface IScarletEventManager
6 | where TEventArgs : EventArgs
7 | {
8 | void AddHandler(TEventSource source, string eventName, EventHandler handler);
9 |
10 | void RemoveHandler(TEventSource source, string eventName, EventHandler handler);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IScarletExceptionHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace MvvmScarletToolkit
5 | {
6 | public interface IScarletExceptionHandler
7 | {
8 | Task Handle(Exception ex);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/IVirtualizationViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using System.Windows.Input;
5 |
6 | namespace MvvmScarletToolkit
7 | {
8 | public interface IVirtualizationViewModel : INotifyPropertyChanged
9 | {
10 | bool IsLoaded { get; }
11 |
12 | ///
13 | /// conditional refresh
14 | ///
15 | ICommand LoadCommand { get; }
16 |
17 | ///
18 | /// explicit refresh, updates filtering and the current children
19 | ///
20 | ICommand RefreshCommand { get; }
21 |
22 | ICommand UnloadCommand { get; }
23 |
24 | Task Load(CancellationToken token);
25 |
26 | Task Refresh(CancellationToken token);
27 |
28 | Task Unload(CancellationToken token);
29 |
30 | bool CanLoad();
31 |
32 | bool CanRefresh();
33 |
34 | bool CanUnload();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/MvvmScarletToolkit.Abstractions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | Library
5 | enable
6 | MvvmScarletToolkit.Abstractions is part of the MvvmScarletToolkit framework, containing interfaces and extensions used by the rest of the framework.
7 | MvvmScarletToolkit,MVVM,C#,Toolkit,Scarlet,Library,.NET,OSS,OpenSource
8 |
9 |
10 |
11 |
12 | all
13 | runtime; build; native; contentfiles; analyzers; buildtransitive
14 |
15 |
16 | all
17 | runtime; build; native; contentfiles; analyzers; buildtransitive
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("MvvmScarletToolkit.Abstractions")]
8 | [assembly: AssemblyDescription("MvvmScarletToolkit.Abstractions is part of the MvvmScarletToolkit framework, containing interfaces and extensions used by the rest of the framework.")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCulture("")]
11 |
12 | // Setting ComVisible to false makes the types in this assembly not visible
13 | // to COM components. If you need to access a type in this assembly from
14 | // COM, set the ComVisible attribute to true on that type.
15 | [assembly: ComVisible(false)]
16 |
17 | // The following GUID is for the ID of the typelib if this project is exposed to COM
18 | [assembly: Guid("4d4558e2-878f-48c8-bbe2-e22db20e9a55")]
19 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Abstractions/readme.md:
--------------------------------------------------------------------------------
1 | # MvvmScarletToolkit.Abstractions
2 |
3 | 
4 |
5 | ## Goals
6 |
7 | This library aims to provide interfaces and extensions that are being used by the rest of the framework.
8 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Avalonia/Implementations/ScarletCommandManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MvvmScarletToolkit
4 | {
5 | ///
6 | /// simple wrapper around
7 | ///
8 | public sealed class ScarletCommandManager : IScarletCommandManager
9 | {
10 | private static readonly Lazy _default = new Lazy(() => new ScarletCommandManager());
11 |
12 | public static IScarletCommandManager Default => _default.Value;
13 |
14 | public event EventHandler? RequerySuggested;
15 |
16 | public void InvalidateRequerySuggested()
17 | {
18 | RequerySuggested?.Invoke(this, EventArgs.Empty);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Avalonia/Implementations/ScarletLocalizationProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Globalization;
3 | using System.Linq;
4 |
5 | namespace MvvmScarletToolkit
6 | {
7 | public sealed class ScarletLocalizationProvider : ILocalizationProvider
8 | {
9 | public IEnumerable Languages { get; }
10 |
11 | public ScarletLocalizationProvider()
12 | {
13 | Languages = Enumerable.Empty();
14 | }
15 |
16 | public string Translate(string key, CultureInfo culture)
17 | {
18 | return key;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Avalonia/Implementations/ScarletWeakEventManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | namespace MvvmScarletToolkit
5 | {
6 | public sealed class ScarletWeakEventManager : IScarletEventManager
7 | {
8 | private readonly WeakEventManager _weakEventManager;
9 | private static readonly Lazy _default = new Lazy(() => new ScarletWeakEventManager());
10 |
11 | public static IScarletEventManager Default => _default.Value;
12 |
13 | public ScarletWeakEventManager()
14 | {
15 | _weakEventManager = new WeakEventManager();
16 | }
17 |
18 | public void AddHandler(INotifyPropertyChanged source, string eventName, EventHandler handler)
19 | {
20 | _weakEventManager.AddEventHandler(handler, eventName);
21 | }
22 |
23 | public void RemoveHandler(INotifyPropertyChanged source, string eventName, EventHandler handler)
24 | {
25 | _weakEventManager.RemoveEventHandler(handler, eventName);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Avalonia/MvvmScarletToolkit.Avalonia.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0-windows;net9.0-windows
4 | Library
5 | enable
6 | MvvmScarletToolkit.Implementations is part of the MvvmScarletToolkit framework, containing concrete implementations for Avalonia that have been abstracted away in the MvvmScarletToolkit.Abstractions library.
7 | MvvmScarletToolkit,MVVM,C#,Toolkit,Scarlet,Avalonia,Library,.NET,OSS,OpenSource
8 |
9 |
10 |
11 |
12 |
13 | all
14 | runtime; build; native; contentfiles; analyzers; buildtransitive
15 |
16 |
17 | all
18 | runtime; build; native; contentfiles; analyzers; buildtransitive
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Commands/Core/ConcurrentCommandDecoratorBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Diagnostics;
4 | using System.Threading.Tasks;
5 |
6 | namespace MvvmScarletToolkit.Commands
7 | {
8 | public abstract class ConcurrentCommandDecoratorBase : ConcurrentCommandBase
9 | {
10 | protected readonly ConcurrentCommandBase Command;
11 |
12 | [Bindable(true, BindingDirection.OneWay)]
13 | public override bool IsBusy => Command.IsBusy;
14 |
15 | [Bindable(true, BindingDirection.OneWay)]
16 | public override Task Completion => Command.Completion;
17 |
18 | protected ConcurrentCommandDecoratorBase(in IScarletCommandManager commandManager, in ConcurrentCommandBase command)
19 | : base(commandManager)
20 | {
21 | Command = command ?? throw new ArgumentNullException(nameof(command));
22 | Command.PropertyChanged += Command_PropertyChanged;
23 | CancelCommand = Command.CancelCommand;
24 | }
25 |
26 | private void Command_PropertyChanged(object sender, PropertyChangedEventArgs e)
27 | {
28 | OnPropertyChanged(e);
29 | }
30 |
31 | [DebuggerStepThrough]
32 | public override sealed async void Execute(object parameter)
33 | {
34 | await ExecuteAsync(parameter)
35 | .ConfigureAwait(true); // return to UI thread here
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Commands/Core/GenericConcurrentCommandBase.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Threading.Tasks;
3 |
4 | namespace MvvmScarletToolkit.Commands
5 | {
6 | ///
7 | /// Base implementation providing interface members for cancellation support and exposing current execution
8 | ///
9 | public abstract class GenericConcurrentCommandBase : ConcurrentCommandBase
10 | {
11 | [Bindable(true, BindingDirection.OneWay)]
12 | public override sealed Task Completion => Execution.TaskCompletion;
13 |
14 | private NotifyTaskCompletion _execution;
15 | [Bindable(true, BindingDirection.OneWay)]
16 | public NotifyTaskCompletion Execution
17 | {
18 | get { return _execution; }
19 | protected set
20 | {
21 | if (SetValue(ref _execution, value))
22 | {
23 | OnPropertyChanged(nameof(Completion));
24 | }
25 | }
26 | }
27 |
28 | protected GenericConcurrentCommandBase(in IScarletCommandManager commandManager)
29 | : base(commandManager)
30 | {
31 | _execution = NotifyTaskCompletion.Completed;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Commands/Core/IgnoreExceptionHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace MvvmScarletToolkit
5 | {
6 | public sealed class IgnoreExceptionHandler : IScarletExceptionHandler
7 | {
8 | private static readonly Lazy _default = new Lazy(() => new IgnoreExceptionHandler());
9 |
10 | public static IScarletExceptionHandler Default => _default.Value;
11 |
12 | public Task Handle(Exception ex)
13 | {
14 | #if DEBUG
15 | System.Diagnostics.Debug.WriteLine(ex.ToString());
16 | #endif
17 |
18 | return Task.CompletedTask;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Commands/Core/NoCancellationCommand.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 |
4 | namespace MvvmScarletToolkit.Commands
5 | {
6 | internal sealed class NoCancellationCommand : ICancelCommand
7 | {
8 | private static readonly Lazy _default = new Lazy(() => new NoCancellationCommand());
9 |
10 | public static NoCancellationCommand Default => _default.Value;
11 |
12 | public CancellationToken Token { get; }
13 |
14 | public event EventHandler? CanExecuteChanged;
15 |
16 | private NoCancellationCommand()
17 | {
18 | }
19 |
20 | public bool CanExecute(object parameter)
21 | {
22 | return false;
23 | }
24 |
25 | public void Dispose()
26 | {
27 | }
28 |
29 | public void Execute(object parameter)
30 | {
31 | }
32 |
33 | public void NotifyCommandFinished()
34 | {
35 | CanExecuteChanged?.Invoke(this, EventArgs.Empty);
36 | }
37 |
38 | public void NotifyCommandStarting()
39 | {
40 | CanExecuteChanged?.Invoke(this, EventArgs.Empty);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Commands/IScarletCommandBuilder.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.Messaging;
2 | using MvvmScarletToolkit.Commands;
3 | using System;
4 | using System.ComponentModel;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace MvvmScarletToolkit
9 | {
10 | public interface IScarletCommandBuilder
11 | {
12 | IScarletExceptionHandler ExceptionHandler { get; }
13 | IScarletCommandManager CommandManager { get; }
14 | IScarletDispatcher Dispatcher { get; }
15 | IMessenger Messenger { get; }
16 | IExitService Exit { get; }
17 | IScarletEventManager WeakEventManager { get; }
18 |
19 | CommandBuilderContext Create(Func execute, Func canExecute);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Commands/MvvmScarletToolkit.Commands.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | Library
5 | enable
6 | MvvmScarletToolkit.Commands is part of the MvvmScarletToolkit framework, containing asynchrnous and synchronous implementations of the ICommand interface for .NET.
7 | MvvmScarletToolkit,MVVM,C#,Toolkit,Scarlet,Library,.NET,OSS,OpenSource
8 |
9 |
10 |
11 |
12 |
13 |
14 | all
15 | runtime; build; native; contentfiles; analyzers; buildtransitive
16 |
17 |
18 | all
19 | runtime; build; native; contentfiles; analyzers; buildtransitive
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Commands/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("MvvmScarletToolkit.Commands")]
9 | [assembly: AssemblyDescription("MvvmScarletToolkit.Commands is part of the MvvmScarletToolkit framework, containing asynchrnous and synchronous implementations of the ICommand interface for .NET.")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCulture("")]
12 |
13 | // Setting ComVisible to false makes the types in this assembly not visible
14 | // to COM components. If you need to access a type in this assembly from
15 | // COM, set the ComVisible attribute to true on that type.
16 | [assembly: ComVisible(false)]
17 |
18 | // The following GUID is for the ID of the typelib if this project is exposed to COM
19 | [assembly: Guid("a85ecf94-f42d-43b2-9c65-c27e2963cf08")]
20 | [assembly: InternalsVisibleTo("MvvmScarletToolkit.Wpf.Tests")]
21 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Commands/readme.md:
--------------------------------------------------------------------------------
1 | # MvvmScarletToolkit.Commands
2 |
3 | 
4 |
5 | ## Goals
6 |
7 | This library aims to provide easy to use [ICommand](https://docs.microsoft.com/en-gb/dotnet/api/system.windows.input.icommand) implementations for use in viewmodels.
8 |
9 | ## Contents
10 |
11 | |class|summary|
12 | |---|---|
13 | |``ConcurrentCommand``|A Task based ``ICommand`` implementation supporting fluent configuration via ``IScarletCommandBuilder``.|
14 |
15 | ## Usage
16 |
17 |
18 | ### ConcurrentCommand\
19 |
20 | ```cs
21 | public class SomeClass
22 | {
23 | public ICommand Command { get; }
24 |
25 | public SomeClass(IScarletCommandBuilder commandBuilder)
26 | {
27 | Command = commandBuilder
28 | .Create(Do, CanDo)
29 | .WithSingleExecution() // prevent from running multiple instances of this command at the same time
30 | .WithBusyNotification(BusyStack) // notify an IBusyStack instance that this command is running
31 | .WithAsyncCancellation() // use an async ICommand implementation for cancellation support
32 | .Build();
33 | }
34 |
35 | private Task Do(CancellationToken token)
36 | {
37 | return Task.Delay(2000);
38 | }
39 |
40 | private bool CanDo()
41 | {
42 | return true;
43 | }
44 | }
45 | ```
46 |
47 |
48 | ## Credits
49 |
50 | ``ConcurrentCommand`` is largely based on Stephen Clearlys blog post: [Async Programming : Patterns for Asynchronous MVVM Applications](https://msdn.microsoft.com/en-us/magazine/dn630647.aspx?f=255&MSPPError=-2147217396)
51 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Incubator/BoolDialogResultViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace MvvmScarletToolkit
2 | {
3 | public sealed class BoolDialogResultViewModel : DialogResultViewModel
4 | {
5 | public BoolDialogResultViewModel(IScarletCommandBuilder commandBuilder)
6 | : base(commandBuilder, false)
7 | {
8 | }
9 |
10 | public BoolDialogResultViewModel(IScarletCommandBuilder commandBuilder, bool model)
11 | : base(commandBuilder, model)
12 | {
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Incubator/MvvmScarletToolkit.Incubator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0-windows;net9.0-windows
4 | Library
5 | true
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Incubator/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | #if NET5_0_OR_GREATER
5 | [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows7.0")]
6 | #endif
7 |
8 | // General Information about an assembly is controlled through the following
9 | // set of attributes. Change these attribute values to modify the information
10 | // associated with an assembly.
11 | [assembly: AssemblyTitle("MvvmScarletToolkit.Incubator")]
12 | [assembly: AssemblyDescription("MvvmScarletToolkit.Incubator is part of the MvvmScarletToolkit framework, containing ideas and features that are still in a concept phase or classes which haven't been useful enough to be publically distributed.")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("67e41cb4-774b-455b-b0fc-86ef13677fb7")]
23 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables.Tests/AttributedBroadCastViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 |
3 | namespace MvvmScarletToolkit.Observables.Tests
4 | {
5 | [ObservableRecipient]
6 | internal sealed partial class AttributedBroadCastViewModel : ObservableObject, ITestViewModel
7 | {
8 | [ObservableProperty]
9 | [NotifyPropertyChangedRecipients]
10 | private string _property;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables.Tests/BroadCastViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using CommunityToolkit.Mvvm.Messaging;
3 |
4 | namespace MvvmScarletToolkit.Observables.Tests
5 | {
6 | internal sealed partial class BroadCastViewModel : ObservableRecipient, ITestViewModel
7 | {
8 | private string property;
9 | public string Property
10 | {
11 | get { return property; }
12 | set { SetProperty(ref property, value, true); }
13 | }
14 |
15 | public BroadCastViewModel(IMessenger messenger)
16 | : base(messenger)
17 | {
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables.Tests/ITestViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace MvvmScarletToolkit.Observables.Tests
4 | {
5 | public interface ITestViewModel : INotifyPropertyChanged
6 | {
7 | string Property { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables.Tests/MvvmScarletToolkit.Observables.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0-windows;net9.0-windows
4 | false
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | all
16 | runtime; build; native; contentfiles; analyzers
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables.Tests/ViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 |
3 | namespace MvvmScarletToolkit.Observables.Tests
4 | {
5 | internal sealed partial class ViewModel : ObservableRecipient
6 | {
7 | [ObservableProperty]
8 | [NotifyPropertyChangedRecipients]
9 | private string _data;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/Extensions/ObservableCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using DynamicData.Binding;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace MvvmScarletToolkit
7 | {
8 | public static class ObservableCollectionExtensions
9 | {
10 | ///
11 | /// in place sort an
12 | ///
13 | ///
14 | /// will undo selection, when collection is bound for example to a ListBox
15 | ///
16 | public static void Sort(this IObservableCollection collection)
17 | where T : IComparable
18 | {
19 | var sorted = collection.OrderBy(x => x).ToList();
20 |
21 | for (var i = 0; i < sorted.Count; i++)
22 | {
23 | collection.Move(collection.IndexOf(sorted[i]), i);
24 | }
25 | }
26 |
27 | ///
28 | /// in place sort an utilizing an
29 | ///
30 | ///
31 | /// will undo selection, when collection is bound for example to a ListBox
32 | ///
33 | public static void Sort(this IObservableCollection collection, IComparer comparer)
34 | {
35 | var sorted = collection.OrderBy(x => x, comparer).ToList();
36 |
37 | for (var i = 0; i < sorted.Count; i++)
38 | {
39 | collection.Move(collection.IndexOf(sorted[i]), i);
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/IChange.cs:
--------------------------------------------------------------------------------
1 | namespace MvvmScarletToolkit
2 | {
3 | public interface IChange
4 | {
5 | bool IsActualChange { get; }
6 | }
7 |
8 | public interface IChange : IChange
9 | {
10 | ///
11 | /// Gets the value that the property had before the change.
12 | ///
13 | T InitialValue { get; }
14 |
15 | ///
16 | /// Gets the value that the property has after the change.
17 | ///
18 | T NewValue { get; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/MvvmScarletToolkit.Observables.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | Library
5 | enable
6 | MvvmScarletToolkit.Observables is part of the MvvmScarletToolkit framework, containing opinionated base classes for viewmodels of the MVVM pattern.
7 | MvvmScarletToolkit,MVVM,C#,Toolkit,Scarlet,Library,.NET,OSS,OpenSource
8 |
9 |
10 |
11 |
12 |
13 |
14 | all
15 | runtime; build; native; contentfiles; analyzers; buildtransitive
16 |
17 |
18 | all
19 | runtime; build; native; contentfiles; analyzers; buildtransitive
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("MvvmScarletToolkit.Observables")]
8 | [assembly: AssemblyDescription("MvvmScarletToolkit.Observables is part of the MvvmScarletToolkit framework, containing opinionated base classes for viewmodels of the MVVM pattern.")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCulture("")]
11 |
12 | // Setting ComVisible to false makes the types in this assembly not visible
13 | // to COM components. If you need to access a type in this assembly from
14 | // COM, set the ComVisible attribute to true on that type.
15 | [assembly: ComVisible(false)]
16 |
17 | // The following GUID is for the ID of the typelib if this project is exposed to COM
18 | [assembly: Guid("3d7bbed6-6056-488d-ae6a-65df15d3d046")]
19 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Base/BusinessViewModelBase_generic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | namespace MvvmScarletToolkit.Observables
5 | {
6 | ///
7 | /// ViewModelBase that bootstraps loading, unloading and refreshing of its content
8 | ///
9 | ///
10 | public abstract class BusinessViewModelBase : BusinessViewModelBase
11 | where TModel : class
12 | {
13 | private TModel? _model;
14 | [Bindable(true, BindingDirection.OneWay)]
15 | public TModel? Model
16 | {
17 | get { return _model; }
18 | protected set { SetProperty(ref _model, value); }
19 | }
20 |
21 | protected BusinessViewModelBase(in IScarletCommandBuilder commandBuilder)
22 | : base(commandBuilder)
23 | {
24 | }
25 |
26 | protected BusinessViewModelBase(in IScarletCommandBuilder commandBuilder, in TModel model)
27 | : base(commandBuilder)
28 | {
29 | _model = model ?? throw new ArgumentNullException(nameof(model));
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Base/DomainViewModelListBase.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.ComponentModel;
5 |
6 | namespace MvvmScarletToolkit.Observables
7 | {
8 | ///
9 | /// Collection ViewModelBase that adds support for paged loading
10 | ///
11 | ///
12 | public abstract partial class DomainViewModelListBase : BusinessViewModelListBase
13 | where TViewModel : class, INotifyPropertyChanged
14 | {
15 | private int _total;
16 | [Bindable(true, BindingDirection.TwoWay)]
17 | public int Total
18 | {
19 | get { return _total; }
20 | protected set { SetProperty(ref _total, value); }
21 | }
22 |
23 | [ObservableProperty]
24 | private int _pageSize;
25 |
26 | [ObservableProperty]
27 | private int _pageIndex;
28 |
29 | [Bindable(true, BindingDirection.OneWay)]
30 | public PagingViewModel Paging { get; }
31 |
32 | protected DomainViewModelListBase(in IScarletCommandBuilder commandBuilder, in IEnumerable pageSizes)
33 | : base(commandBuilder)
34 | {
35 | Paging = new PagingViewModel(commandBuilder, this, new ReadOnlyObservableCollection(new ObservableCollection(pageSizes)));
36 | }
37 |
38 | protected override void Dispose(bool disposing)
39 | {
40 | if (IsDisposed)
41 | {
42 | return;
43 | }
44 |
45 | if (disposing)
46 | {
47 | Paging.Dispose();
48 | }
49 |
50 | base.Dispose(disposing);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Base/Messages/ViewModelListBaseSelectionChanged.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.Messaging.Messages;
2 |
3 | namespace MvvmScarletToolkit.Observables
4 | {
5 | public sealed class ViewModelListBaseSelectionChanged : ValueChangedMessage
6 | {
7 | public object Sender { get; }
8 |
9 | public ViewModelListBaseSelectionChanged(in object sender, in TViewModel content)
10 | : base(content)
11 | {
12 | Sender = sender ?? throw new System.ArgumentNullException(nameof(sender));
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Base/Messages/ViewModelListBaseSelectionChanging.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.Messaging.Messages;
2 |
3 | namespace MvvmScarletToolkit.Observables
4 | {
5 | public sealed class ViewModelListBaseSelectionChanging : ValueChangedMessage
6 | {
7 | public object Sender { get; }
8 |
9 | public ViewModelListBaseSelectionChanging(in object sender, in TViewModel content)
10 | : base(content)
11 | {
12 | Sender = sender ?? throw new System.ArgumentNullException(nameof(sender));
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Base/Messages/ViewModelListBaseSelectionsChanged.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.Messaging.Messages;
2 | using System.Collections.Generic;
3 |
4 | namespace MvvmScarletToolkit.Observables
5 | {
6 | public sealed class ViewModelListBaseSelectionsChanged : ValueChangedMessage>
7 | {
8 | public ViewModelListBaseSelectionsChanged(in IEnumerable content)
9 | : base(content)
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Base/Rx/INotifyRefreshRequired.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reactive;
3 |
4 | namespace MvvmScarletToolkit
5 | {
6 | public interface INotifyRefreshRequired
7 | {
8 | IObservable GetObservable();
9 |
10 | void Notify();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Base/Rx/NotifyRefreshRequiredAdapter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reactive;
3 | using System.Reactive.Linq;
4 |
5 | namespace MvvmScarletToolkit
6 | {
7 | ///
8 | /// Adapter class around
9 | ///
10 | public sealed class NotifyRefreshRequiredAdapter : INotifyRefreshRequired
11 | {
12 | private event EventHandler? RefreshRequired;
13 |
14 | public void Notify()
15 | {
16 | RefreshRequired?.Invoke(this, Unit.Default);
17 | }
18 |
19 | public IObservable GetObservable()
20 | {
21 | return Observable
22 | .FromEventPattern, Unit>(e => RefreshRequired += e, e => RefreshRequired -= e)
23 | .Select(x => x.EventArgs);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Base/ViewModelBase_generic.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace MvvmScarletToolkit.Observables
4 | {
5 | ///
6 | /// Generic version of exposing an injected (model)class
7 | ///
8 | public abstract class ViewModelBase : ViewModelBase
9 | where TModel : class
10 | {
11 | private TModel? _model;
12 | [Bindable(true, BindingDirection.OneWay)]
13 | public TModel? Model
14 | {
15 | get { return _model; }
16 | protected set { SetProperty(ref _model, value); }
17 | }
18 |
19 | protected ViewModelBase(in IScarletCommandBuilder commandBuilder)
20 | : base(commandBuilder)
21 | {
22 | }
23 |
24 | protected ViewModelBase(in IScarletCommandBuilder commandBuilder, in TModel model)
25 | : this(commandBuilder)
26 | {
27 | _model = model;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/EnumViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | namespace MvvmScarletToolkit.Observables
5 | {
6 | public sealed class EnumViewModel
7 | {
8 | public static EnumViewModel Create(in TEnum value)
9 | where TEnum : Enum
10 | {
11 | return new EnumViewModel(value, value.GetAttributeOfType()?.Description);
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/EnumViewModel_generic.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using System;
3 |
4 | namespace MvvmScarletToolkit.Observables
5 | {
6 | public partial class EnumViewModel : ViewModelContainer
7 | where T : Enum
8 | {
9 | [ObservableProperty]
10 | private string _displayName;
11 |
12 | public EnumViewModel(in T value, in string? displayName)
13 | : base(value)
14 | {
15 | _displayName = displayName ?? "Undefined";
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Localization/ServiceExtensions.cs:
--------------------------------------------------------------------------------
1 | using MvvmScarletToolkit.Observables;
2 | using System.ComponentModel;
3 |
4 | namespace MvvmScarletToolkit
5 | {
6 | public static class ServiceExtensions
7 | {
8 | public static ILocalizationViewModel CreateViewModel(this ILocalizationService localizationService, in IScarletEventManager weakEventManager, in string key)
9 | {
10 | return new LocalizationViewModel(weakEventManager, localizationService, key);
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Localization/samples.md:
--------------------------------------------------------------------------------
1 | [back](../../readme.md)
2 |
3 | TODO
4 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Navigation/Scene.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using System;
3 |
4 | namespace MvvmScarletToolkit.Observables
5 | {
6 | public partial class Scene : ObservableObject
7 | {
8 | [ObservableProperty]
9 | private object? _content;
10 |
11 | [ObservableProperty]
12 | private bool _isSelected;
13 |
14 | [ObservableProperty]
15 | public int _sequence;
16 |
17 | public ILocalizationViewModel Localization { get; }
18 |
19 | public Scene(in ILocalizationViewModel localizationViewModel)
20 | {
21 | Localization = localizationViewModel ?? throw new ArgumentNullException(nameof(localizationViewModel));
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Navigation/Scenes.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace MvvmScarletToolkit.Observables
5 | {
6 | public abstract class Scenes : ViewModelListBase
7 | {
8 | private readonly LocalizationsViewModel _localizationsViewModel;
9 | private readonly List _disposeables;
10 |
11 | private bool _disposed;
12 |
13 | protected Scenes(in IScarletCommandBuilder commandBuilder, in LocalizationsViewModel localizationsViewModel)
14 | : base(commandBuilder)
15 | {
16 | _localizationsViewModel = localizationsViewModel ?? throw new ArgumentNullException(nameof(LocalizationsViewModel));
17 | _disposeables = new List();
18 | }
19 |
20 | protected void Add(string key, object content)
21 | {
22 | var localization = _localizationsViewModel.CreateViewModel(WeakEventManager, key);
23 | _disposeables.Add(localization);
24 |
25 | var viewmodel = new Scene(localization)
26 | {
27 | Content = content,
28 | Sequence = Items.Count,
29 | };
30 |
31 | _items.Add(viewmodel);
32 | }
33 |
34 | protected override void Dispose(bool disposing)
35 | {
36 | if (_disposed)
37 | {
38 | return;
39 | }
40 |
41 | if (disposing)
42 | {
43 | _items.Clear();
44 |
45 | for (var i = 0; i < _disposeables.Count; i++)
46 | {
47 | _disposeables[i].Dispose();
48 | _disposeables.Clear();
49 | }
50 | }
51 |
52 | base.Dispose(disposing);
53 | _disposed = true;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Navigation/samples.md:
--------------------------------------------------------------------------------
1 | [back](../../readme.md)
2 |
3 | TODO
4 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/Paging/IPagedDataProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace MvvmScarletToolkit
7 | {
8 | public interface IPagedDataProvider
9 | where TViewModel : class, INotifyPropertyChanged
10 | {
11 | Task> Get(int index, int count, CancellationToken token);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/State/BusyStack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Threading;
4 |
5 | namespace MvvmScarletToolkit.Observables
6 | {
7 | ///
8 | /// Will notify its owner via a provided action on if it contains more tokens
9 | ///
10 | public sealed class BusyStack : IBusyStack
11 | {
12 | private readonly Action _onChanged;
13 |
14 | private int _items;
15 |
16 | public BusyStack(in Action onChanged)
17 | {
18 | _onChanged = onChanged ?? throw new ArgumentNullException(nameof(onChanged));
19 | }
20 |
21 | public void Pull()
22 | {
23 | var oldValue = _items > 0;
24 | Interlocked.Decrement(ref _items);
25 | var newValue = _items > 0;
26 |
27 | if (oldValue.Equals(newValue))
28 | {
29 | return;
30 | }
31 |
32 | InvokeOnChanged(newValue);
33 | }
34 |
35 | public void Push()
36 | {
37 | var oldValue = _items > 0;
38 | Interlocked.Increment(ref _items);
39 | var newValue = _items > 0;
40 |
41 | if (oldValue.Equals(newValue))
42 | {
43 | return;
44 | }
45 |
46 | InvokeOnChanged(newValue);
47 | }
48 |
49 | ///
50 | /// Returns a new thats associated with instance of a
51 | ///
52 | /// a new
53 | [DebuggerStepThrough]
54 | public IDisposable GetToken()
55 | {
56 | return new BusyToken(this);
57 | }
58 |
59 | [DebuggerStepThrough]
60 | private void InvokeOnChanged(bool newValue)
61 | {
62 | _onChanged(newValue);
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/State/BusyToken.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MvvmScarletToolkit.Observables
4 | {
5 | public struct BusyToken : IDisposable
6 | {
7 | private readonly IBusyStack _busyStack;
8 |
9 | private bool _disposed;
10 |
11 | public BusyToken(in IBusyStack busyStack)
12 | {
13 | _busyStack = busyStack ?? throw new ArgumentNullException(nameof(busyStack));
14 | _disposed = false;
15 |
16 | busyStack.Push();
17 | }
18 |
19 | public void Dispose()
20 | {
21 | if (_disposed)
22 | {
23 | return;
24 | }
25 |
26 | _busyStack.Pull();
27 | _disposed = true;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/State/DisposalToken.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 |
4 | namespace MvvmScarletToolkit.Observables
5 | {
6 | public sealed class DisposalToken : IDisposable
7 | {
8 | private readonly ConcurrentDictionary, object> _observerCollection;
9 | private readonly IObserver _observer;
10 |
11 | private bool _disposed;
12 |
13 | public DisposalToken(in IObserver observer, in ConcurrentDictionary, object> observerCollection)
14 | {
15 | _observerCollection = observerCollection ?? throw new ArgumentNullException(nameof(observerCollection));
16 | _observer = observer ?? throw new ArgumentNullException(nameof(observer));
17 |
18 | #pragma warning disable CS8603 // Possible null reference return.
19 | _ = _observerCollection.AddOrUpdate(observer, addValueFactory: _ => default, updateValueFactory: (_, __) => default);
20 | #pragma warning restore CS8603 // Possible null reference return.
21 | }
22 |
23 | public void Dispose()
24 | {
25 | if (_disposed)
26 | {
27 | return;
28 | }
29 |
30 | _observerCollection.TryRemove(_observer, out _);
31 | _disposed = true;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/State/samples.md:
--------------------------------------------------------------------------------
1 | [back](../../readme.md)
2 |
3 | TODO
4 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/VersionViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using System.Collections.Generic;
3 |
4 | namespace MvvmScarletToolkit.Observables
5 | {
6 | ///
7 | /// Helper viewmodel for tracking changes
8 | ///
9 | /// literally any c# object
10 | public class VersionViewModel : ObservableObject
11 | {
12 | protected bool HasChanged { get; private set; }
13 |
14 | ///
15 | /// original value
16 | ///
17 | public T Default { get; }
18 |
19 | private T _current;
20 | ///
21 | /// new value
22 | ///
23 | public virtual T Current
24 | {
25 | get { return _current; }
26 | set
27 | {
28 | if (SetProperty(ref _current, value))
29 | {
30 | if (!EqualityComparer.Default.Equals(_current, Default))
31 | {
32 | HasChanged = true;
33 | }
34 |
35 | OnPropertyChanged(nameof(CurrentOrDefault));
36 | }
37 | }
38 | }
39 |
40 | public T CurrentOrDefault => HasChanged ? Current : Default;
41 |
42 | #pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable.
43 |
44 | public VersionViewModel(in T defaultValue)
45 | {
46 | Default = defaultValue;
47 | }
48 |
49 | public VersionViewModel(in T defaultValue, in T current)
50 | {
51 | Default = defaultValue;
52 | Current = current;
53 | }
54 |
55 | #pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable.
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Observables/ViewModels/ViewModelContainer.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 |
3 | namespace MvvmScarletToolkit
4 | {
5 | ///
6 | /// Generic wrapper viewmodel to add binding support to any c# object
7 | ///
8 | ///
9 | public partial class ViewModelContainer : ObservableObject
10 | {
11 | [ObservableProperty]
12 | private T _value;
13 |
14 | public ViewModelContainer(in T value)
15 | {
16 | _value = value;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using Jot;
2 | using Jot.Storage;
3 | using MvvmScarletToolkit.Observables;
4 | using System;
5 | using System.Runtime.Versioning;
6 | using System.Threading;
7 | using System.Windows;
8 |
9 | namespace MvvmScarletToolkit.Wpf.Samples
10 | {
11 | [SupportedOSPlatform("windows7.0")]
12 | public partial class App : Application
13 | {
14 | private readonly Tracker _tracker;
15 |
16 | public App()
17 | {
18 | _tracker = new Tracker(new JsonFileStore(Environment.SpecialFolder.ApplicationData));
19 | }
20 |
21 | protected override void OnStartup(StartupEventArgs e)
22 | {
23 | base.OnStartup(e);
24 |
25 | _tracker.Configure()
26 | .Id(w => w.Name, $"[Width={SystemParameters.VirtualScreenWidth},Height{SystemParameters.VirtualScreenHeight}]")
27 | .Properties(w => new { w.Height, w.Width, w.Left, w.Top, w.WindowState })
28 | .PersistOn(nameof(Window.Closing))
29 | .StopTrackingOn(nameof(Window.Closing));
30 |
31 | var navigation = new NavigationViewModel(SynchronizationContext.Current, ScarletCommandBuilder.Default, new LocalizationsViewModel(new ScarletLocalizationProvider()));
32 |
33 | var window = new MainWindow(_tracker, navigation);
34 |
35 | window.Show();
36 | }
37 |
38 | protected override async void OnExit(ExitEventArgs e)
39 | {
40 | base.OnExit(e);
41 |
42 | await ScarletExitService.Default.ShutDown().ConfigureAwait(false);
43 |
44 | _tracker.PersistAll();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/AsyncState/AsyncStateViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using MvvmScarletToolkit.Observables;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace MvvmScarletToolkit.Wpf.Samples
7 | {
8 | public sealed partial class AsyncStateViewModel : BusinessViewModelBase
9 | {
10 | [ObservableProperty]
11 | private string _displayName;
12 |
13 | [ObservableProperty]
14 | private bool _isSelected;
15 |
16 | public AsyncStateViewModel(IScarletCommandBuilder commandBuilder)
17 | : base(commandBuilder)
18 | {
19 | DisplayName = "unknown";
20 | }
21 |
22 | public AsyncStateViewModel(IScarletCommandBuilder commandBuilder, string displayName)
23 | : this(commandBuilder)
24 | {
25 | DisplayName = displayName;
26 | }
27 |
28 | protected override Task UnloadInternal(CancellationToken token)
29 | {
30 | return Task.Delay(2000, token);
31 | }
32 |
33 | protected override Task RefreshInternal(CancellationToken token)
34 | {
35 | return Task.Delay(2000, token);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/ContextMenu/ContextMenuViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using System.Collections.ObjectModel;
3 |
4 | namespace MvvmScarletToolkit.Wpf.Samples
5 | {
6 | public sealed partial class ContextMenuViewModel : ObservableObject
7 | {
8 | public string Name { get; } = "Test";
9 | public ObservableCollection Items { get; }
10 |
11 | public ContextMenuViewModel()
12 | {
13 | Items = new ObservableCollection();
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/ContextMenu/ContextMenuViewModels.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using System.Collections.ObjectModel;
3 |
4 | namespace MvvmScarletToolkit.Wpf.Samples
5 | {
6 | public sealed partial class ContextMenuViewModels : ObservableObject
7 | {
8 | public ObservableCollection Items { get; }
9 |
10 | public ContextMenuViewModels()
11 | {
12 | Items = new ObservableCollection()
13 | {
14 | new ContextMenuViewModel(),
15 | };
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/DataGrid/DataGridDataProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 |
7 | namespace MvvmScarletToolkit.Wpf.Samples
8 | {
9 | public sealed class DataGridDataProvider : IPagedDataProvider
10 | {
11 | private readonly IScarletCommandBuilder _scarletCommandBuilder;
12 | private readonly List _cache;
13 |
14 | public DataGridDataProvider(IScarletCommandBuilder scarletCommandBuilder, int pageCount, int pageSize)
15 | {
16 | _cache = new List(pageCount * pageSize);
17 | _scarletCommandBuilder = scarletCommandBuilder ?? throw new ArgumentNullException(nameof(scarletCommandBuilder));
18 |
19 | var page = 1;
20 | for (var i = 0; i < pageCount * pageSize; i++)
21 | {
22 | if (i % pageSize == 0)
23 | {
24 | page++;
25 | }
26 | _cache.Add(new DataGridRowViewModel(_scarletCommandBuilder, page)
27 | {
28 | Id = i,
29 | CreatedOn = DateTime.Now,
30 | Name = Guid.NewGuid().ToString(),
31 | Color = $"#cc{i * 2:X2}{i * 3:X2}",
32 | });
33 | }
34 | }
35 |
36 | public Task> Get(int index, int count, CancellationToken token)
37 | {
38 | return Task.FromResult>(_cache.AsQueryable().TryPage(index, count).ToList());
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/DialogViewModel.cs:
--------------------------------------------------------------------------------
1 | using MvvmScarletToolkit.Observables;
2 | using System;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using System.Windows.Input;
6 |
7 | namespace MvvmScarletToolkit.Wpf.Samples
8 | {
9 | public class DialogViewModel : ViewModelBase
10 | {
11 | public ICommand RunCommand { get; }
12 |
13 | public BoolDialogResultViewModel DialogResult { get; }
14 |
15 | public DialogViewModel(IScarletCommandBuilder commandBuilder)
16 | : base(commandBuilder)
17 | {
18 | RunCommand = CommandBuilder.Create(Run, CanRun)
19 | .WithBusyNotification(BusyStack)
20 | .WithSingleExecution()
21 | .WithAsyncCancellation()
22 | .Build();
23 |
24 | DialogResult = new BoolDialogResultViewModel(commandBuilder);
25 | }
26 |
27 | private async Task Run(CancellationToken token)
28 | {
29 | using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
30 | using var linked = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, token);
31 | await DialogResult.Show(linked.Token).ConfigureAwait(false);
32 | }
33 |
34 | private bool CanRun()
35 | {
36 | return !IsBusy;
37 | }
38 |
39 | protected override void Dispose(bool disposing)
40 | {
41 | if (disposing)
42 | {
43 | DialogResult.Dispose();
44 | }
45 |
46 | base.Dispose(disposing);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/Enums/EnumViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Samples
4 | {
5 | public sealed partial class EnumViewModel : ObservableObject
6 | {
7 | [ObservableProperty]
8 | private ViewModelEnum _value;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/Enums/ViewModelEnum.cs:
--------------------------------------------------------------------------------
1 | namespace MvvmScarletToolkit.Wpf.Samples
2 | {
3 | public enum ViewModelEnum
4 | {
5 | None,
6 | SomeValue,
7 | AnotherValue
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/FormViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Samples
4 | {
5 | public sealed partial class FormViewModel : ObservableObject
6 | {
7 | [ObservableProperty]
8 | private string _maxLengthInput;
9 |
10 | [ObservableProperty]
11 | private int _maxLength;
12 |
13 | [ObservableProperty]
14 | private string _regex;
15 |
16 | partial void OnMaxLengthInputChanged(string value)
17 | {
18 | if (int.TryParse(value, out var maxLength))
19 | {
20 | MaxLength = maxLength;
21 | }
22 | }
23 |
24 | public FormViewModel()
25 | {
26 | Regex = "^\\d+$";
27 | MaxLengthInput = "10";
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/Geometry/GeometryContainer.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Media;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Samples
4 | {
5 | public sealed class GeometryContainer : ViewModelContainer
6 | {
7 | public GeometryContainer(Geometry value)
8 | : base(value)
9 | {
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/Geometry/GeometryRenderViewModel.cs:
--------------------------------------------------------------------------------
1 | using MvvmScarletToolkit.Observables;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Media;
9 |
10 | namespace MvvmScarletToolkit.Wpf.Samples
11 | {
12 | public sealed class GeometryRenderViewModel : BusinessViewModelListBase
13 | {
14 | private readonly Typeface _typeface;
15 | private readonly NumberSubstitution _numberSubstitution;
16 |
17 | private readonly IEnumerable _geomtries;
18 |
19 | public GeometryRenderViewModel(IScarletCommandBuilder commandBuilder)
20 | : base(commandBuilder)
21 | {
22 | _typeface = new Typeface("Tahoma");
23 | _numberSubstitution = new NumberSubstitution();
24 |
25 | _geomtries = Enumerable.Range(0, 5000)
26 | .Select(c => (c % (97 - 32)) + 32)
27 | .Select(c => (char)c)
28 | .Select(c => new GeometryContainer(BuildGeometry(new string(c, 1), _typeface, _numberSubstitution)))
29 | .ToArray();
30 | }
31 |
32 | private static Geometry BuildGeometry(string charachters, Typeface typeface, NumberSubstitution numberSubstitution)
33 | {
34 | var result = new FormattedText(charachters, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 24, Brushes.Black, numberSubstitution, TextFormattingMode.Display, 90)
35 | .BuildGeometry(new Point(9, 9));
36 |
37 | result.Freeze();
38 |
39 | return result;
40 | }
41 |
42 | protected override Task RefreshInternal(CancellationToken token)
43 | {
44 | return AddRange(_geomtries, token);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/Image/ImageFactory.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 |
4 | namespace MvvmScarletToolkit.Wpf.Samples
5 | {
6 | public class ImageFactory
7 | {
8 | private readonly IScarletCommandBuilder _commandBuilder;
9 |
10 | public ImageFactory(IScarletCommandBuilder commandBuilder)
11 | {
12 | _commandBuilder = commandBuilder ?? throw new System.ArgumentNullException(nameof(commandBuilder));
13 | }
14 |
15 | public IEnumerable GetImageList()
16 | {
17 | var assembly = typeof(ImageFactory).Assembly;
18 |
19 | var index = 0;
20 | foreach (var name in assembly.GetManifestResourceNames())
21 | {
22 | if (name.EndsWith(".jpg"))
23 | {
24 | yield return new Image(_commandBuilder, assembly)
25 | {
26 | IsSelected = index == 0,
27 | DisplayName = Path.GetFileName(name),
28 | Path = name,
29 | Sequence = index,
30 | };
31 |
32 | index++;
33 | }
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/Image/Images.cs:
--------------------------------------------------------------------------------
1 | using MvvmScarletToolkit.Observables;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 |
5 | namespace MvvmScarletToolkit.Wpf.Samples
6 | {
7 | public class Images : BusinessViewModelListBase
8 | {
9 | private readonly ImageFactory _imageFactory;
10 |
11 | public Images(IScarletCommandBuilder commandBuilder, ImageFactory imageFactory)
12 | : base(commandBuilder)
13 | {
14 | _imageFactory = imageFactory ?? throw new System.ArgumentNullException(nameof(imageFactory));
15 | }
16 |
17 | protected override Task RefreshInternal(CancellationToken token)
18 | {
19 | return AddRange(_imageFactory.GetImageList(), token);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/ObservableDictionaryViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using CommunityToolkit.Mvvm.Input;
3 | using MvvmScarletToolkit.Observables;
4 | using System;
5 | using System.Linq;
6 |
7 | namespace MvvmScarletToolkit.Wpf.Samples
8 | {
9 | internal sealed partial class ObservableDictionaryViewModel : ObservableObject
10 | {
11 | public ObservableDictionary Items { get; }
12 |
13 | public ObservableDictionaryViewModel()
14 | {
15 | Items = new ObservableDictionary()
16 | {
17 | [0] = Guid.NewGuid(),
18 | [1] = Guid.NewGuid(),
19 | [2] = Guid.NewGuid(),
20 | [3] = Guid.NewGuid(),
21 | [4] = Guid.NewGuid(),
22 | };
23 | }
24 |
25 | [RelayCommand]
26 | private void Add()
27 | {
28 | if (Items.Count > 0)
29 | {
30 | Items.Add(Items.MaxBy(p => p.Key).Key + 1, Guid.NewGuid());
31 | }
32 | else
33 | {
34 | Items.Add(0, Guid.NewGuid());
35 | }
36 | }
37 |
38 | [RelayCommand(CanExecute = nameof(CanRemove))]
39 | private void Remove()
40 | {
41 | Items.Remove(Items.First());
42 | }
43 |
44 | private bool CanRemove()
45 | {
46 | return Items.Count > 0;
47 | }
48 |
49 | [RelayCommand]
50 | private void Clear()
51 | {
52 | Items.Clear();
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/PasswordViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Samples
4 | {
5 | public sealed partial class PasswordViewModel : ObservableObject
6 | {
7 | [ObservableProperty]
8 | private string _password;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/Process/ProcessData.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using System;
3 |
4 | namespace MvvmScarletToolkit.Wpf.Samples
5 | {
6 | public sealed partial class ProcessData : ObservableObject
7 | {
8 | public string Message { get; }
9 | public DateTime TimeStamp { get; }
10 |
11 | public ProcessData(string message, DateTime timeStamp)
12 | {
13 | Message = message;
14 | TimeStamp = timeStamp;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/Process/ProcessErrorData.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using System;
3 |
4 | namespace MvvmScarletToolkit.Wpf.Samples
5 | {
6 | public sealed partial class ProcessErrorData : ObservableObject
7 | {
8 | public string Message { get; }
9 | public DateTime TimeStamp { get; }
10 |
11 | public ProcessErrorData(string message, DateTime timeStamp)
12 | {
13 | Message = message;
14 | TimeStamp = timeStamp;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/Process/ProcessingImagesViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Samples
4 | {
5 | public partial class ProcessingImagesViewModel : ObservableObject
6 | {
7 | private Images _source;
8 | public Images Source
9 | {
10 | get { return _source; }
11 | private set { SetProperty(ref _source, value); }
12 | }
13 |
14 | private Images _target;
15 | public Images Target
16 | {
17 | get { return _target; }
18 | private set { SetProperty(ref _target, value); }
19 | }
20 |
21 | public ProcessingImagesViewModel(IScarletCommandBuilder commandBuilder, ImageFactory imageFactory)
22 | {
23 | Source = new Images(commandBuilder, imageFactory);
24 | Target = new Images(commandBuilder, imageFactory);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/ToastsViewmodel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using MvvmScarletToolkit.Observables;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using System.Windows.Input;
6 |
7 | namespace MvvmScarletToolkit.Wpf.Samples
8 | {
9 | public sealed partial class ToastsViewModel : ViewModelBase
10 | {
11 | public ICommand ShowToastCommand { get; }
12 | public ICommand ShowManyToastsCommand { get; }
13 |
14 | [ObservableProperty]
15 | private ToastType _toastType;
16 |
17 | [ObservableProperty]
18 | private string _title;
19 |
20 | [ObservableProperty]
21 | private string _body;
22 |
23 | [ObservableProperty]
24 | private bool _persist;
25 |
26 | public ToastsViewModel(IScarletCommandBuilder commandBuilder)
27 | : base(commandBuilder)
28 | {
29 | ShowToastCommand = commandBuilder
30 | .Create(ShowToastImpl)
31 | .Build();
32 |
33 | ShowManyToastsCommand = commandBuilder
34 | .Create(ShowManyToastsImpl)
35 | .Build();
36 |
37 | _title = "Toast-Title";
38 | _body = "Toast-Body";
39 | _toastType = ToastType.Success;
40 | }
41 |
42 | private Task ShowToastImpl(CancellationToken token)
43 | {
44 | ToastService.Default.Show(Title, Body, ToastType, Persist);
45 |
46 | return Task.CompletedTask;
47 | }
48 |
49 | private Task ShowManyToastsImpl(CancellationToken token)
50 | {
51 | for (var i = 0; i < 100; i++)
52 | {
53 | ToastService.Default.Show(Title, Body, ToastType, Persist);
54 | }
55 |
56 | return Task.CompletedTask;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Features/Virtualization/DataEntryViewModel.cs:
--------------------------------------------------------------------------------
1 | using CommunityToolkit.Mvvm.ComponentModel;
2 | using MvvmScarletToolkit.Observables;
3 | using System;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 |
7 | namespace MvvmScarletToolkit.Wpf.Samples
8 | {
9 | public sealed partial class DataEntryViewModel : BusinessViewModelBase
10 | {
11 | [ObservableProperty]
12 | private string _message;
13 |
14 | [ObservableProperty]
15 | private DateTime _createdOn;
16 |
17 | [ObservableProperty]
18 | private Guid _id;
19 |
20 | [ObservableProperty]
21 | private bool _isSelected;
22 |
23 | public DataEntryViewModel(IScarletCommandBuilder commandBuilder)
24 | : base(commandBuilder)
25 | {
26 | Id = Guid.NewGuid();
27 | }
28 |
29 | protected override Task UnloadInternal(CancellationToken token)
30 | {
31 | CreatedOn = DateTime.MinValue;
32 | Message = "";
33 |
34 | return Task.CompletedTask;
35 | }
36 |
37 | protected override Task RefreshInternal(CancellationToken token)
38 | {
39 | CreatedOn = DateTime.UtcNow;
40 | Message = CreatedOn.GetHashCode().ToString();
41 |
42 | return Task.CompletedTask;
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using Jot;
2 | using System;
3 | using System.Windows;
4 |
5 | namespace MvvmScarletToolkit.Wpf.Samples
6 | {
7 | public partial class MainWindow
8 | {
9 | public Tracker Tracker
10 | {
11 | get { return (Tracker)GetValue(TrackerProperty); }
12 | set { SetValue(TrackerProperty, value); }
13 | }
14 |
15 | public static readonly DependencyProperty TrackerProperty = DependencyProperty.Register(
16 | nameof(Tracker),
17 | typeof(Tracker),
18 | typeof(MainWindow),
19 | new PropertyMetadata(null));
20 |
21 | public MainWindow(Tracker tracker, NavigationViewModel navigationViewModel)
22 | {
23 | ArgumentNullException.ThrowIfNull(tracker, nameof(tracker));
24 | ArgumentNullException.ThrowIfNull(navigationViewModel, nameof(navigationViewModel));
25 |
26 | InitializeComponent();
27 |
28 | tracker.Track(this);
29 |
30 | SetCurrentValue(TrackerProperty, tracker);
31 |
32 | DataContext = navigationViewModel;
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 | using System.Windows;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("MvvmScarletToolkit.Wpf.Samples")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCulture("")]
12 |
13 | // Setting ComVisible to false makes the types in this assembly not visible
14 | // to COM components. If you need to access a type in this assembly from
15 | // COM, set the ComVisible attribute to true on that type.
16 | [assembly: ComVisible(false)]
17 |
18 | //In order to begin building localizable applications, set
19 | //CultureYouAreCodingWith in your .csproj file
20 | //inside a . For example, if you are using US english
21 | //in your source files, set the to en-US. Then uncomment
22 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
23 | //the line below to match the UICulture setting in the project file.
24 |
25 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
26 |
27 | [assembly: ThemeInfo(
28 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
29 | //(used if a resource is not found in the page,
30 | // or application resource dictionaries)
31 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
32 | //(used if a resource is not found in the page,
33 | // app, or any theme specific resource dictionaries)
34 | )]
35 | [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows7.0")]
36 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Properties/PublishProfiles/FolderProfile.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | Release
8 | Any CPU
9 | bin\Release\net6.0-windows\win10-x64\publish\win10-x64\
10 | FileSystem
11 | net6.0-windows
12 | win10-x64
13 | true
14 | True
15 | true
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Resources/Death_to_Stock_Photography_RideorDie_8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insire/MvvmScarletToolkit/c2cfa12e4d4f3e1b352ed3c1b32efe77858c0800/src/MvvmScarletToolkit.Wpf.Samples/Resources/Death_to_Stock_Photography_RideorDie_8.jpg
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Resources/Moon_Color_Hypersaturated_Stars_900.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insire/MvvmScarletToolkit/c2cfa12e4d4f3e1b352ed3c1b32efe77858c0800/src/MvvmScarletToolkit.Wpf.Samples/Resources/Moon_Color_Hypersaturated_Stars_900.jpg
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Resources/wallhaven-245035.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insire/MvvmScarletToolkit/c2cfa12e4d4f3e1b352ed3c1b32efe77858c0800/src/MvvmScarletToolkit.Wpf.Samples/Resources/wallhaven-245035.jpg
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Resources/wallhaven-319605.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insire/MvvmScarletToolkit/c2cfa12e4d4f3e1b352ed3c1b32efe77858c0800/src/MvvmScarletToolkit.Wpf.Samples/Resources/wallhaven-319605.jpg
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Resources/wallhaven-401406.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insire/MvvmScarletToolkit/c2cfa12e4d4f3e1b352ed3c1b32efe77858c0800/src/MvvmScarletToolkit.Wpf.Samples/Resources/wallhaven-401406.jpg
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Samples/Resources/wallhaven-75354.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Insire/MvvmScarletToolkit/c2cfa12e4d4f3e1b352ed3c1b32efe77858c0800/src/MvvmScarletToolkit.Wpf.Samples/Resources/wallhaven-75354.jpg
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Tests/IsNotNullOrEmptyTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Tests
4 | {
5 | public sealed class IsNotNullOrEmptyTests
6 | {
7 | [Test]
8 | public void Convert_Should_Return_True_For_Unsupported_DataType()
9 | {
10 | var converter = new IsNotNullOrEmpty();
11 |
12 | Assert.Multiple(() =>
13 | {
14 | Assert.That(converter.Convert(new object(), null, null, null), Is.EqualTo(true));
15 | Assert.That(converter.Convert(1, null, null, null), Is.EqualTo(true));
16 | Assert.That(converter.Convert("not null", null, null, null), Is.EqualTo(true));
17 | });
18 | }
19 |
20 | [Test]
21 | public void Convert_Should_Return_False_For_NullOrEmpty()
22 | {
23 | var converter = new IsNotNullOrEmpty();
24 |
25 | Assert.Multiple(() =>
26 | {
27 | Assert.That(converter.Convert(null, null, null, null), Is.EqualTo(false));
28 | Assert.That(converter.Convert(string.Empty, null, null, null), Is.EqualTo(false));
29 | });
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Tests/IsNotNullOrWhiteSpaceTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Tests
4 | {
5 | public sealed class IsNotNullOrWhiteSpaceTests
6 | {
7 | [Test]
8 | public void Convert_Should_Return_False_For_Unsupported_DataType()
9 | {
10 | var converter = new IsNotNullOrWhiteSpace();
11 |
12 | Assert.Multiple(() =>
13 | {
14 | Assert.That(converter.Convert(1, null, null, null), Is.EqualTo(false));
15 | Assert.That(converter.Convert(new object(), null, null, null), Is.EqualTo(false));
16 | });
17 | }
18 |
19 | [Test]
20 | public void Convert_Should_Return_True_For_NullOrWhiteSpacey()
21 | {
22 | var converter = new IsNotNullOrWhiteSpace();
23 |
24 | Assert.Multiple(() =>
25 | {
26 | Assert.That(converter.Convert(null, null, null, null), Is.EqualTo(false));
27 | Assert.That(converter.Convert(string.Empty, null, null, null), Is.EqualTo(false));
28 | Assert.That(converter.Convert(" ", null, null, null), Is.EqualTo(false));
29 | });
30 | }
31 |
32 | [Test]
33 | public void Convert_Should_Return_True_For_NonNullOrWhiteSpace()
34 | {
35 | var converter = new IsNotNullOrWhiteSpace();
36 |
37 | Assert.That(converter.Convert("not null", null, null, null), Is.EqualTo(true));
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Tests/IsNotNullTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Tests
4 | {
5 | public sealed class IsNotNullTests
6 | {
7 | [Test]
8 | public void Convert_Should_Return_True_For_Anything_But_Null()
9 | {
10 | var converter = new IsNotNull();
11 |
12 | Assert.Multiple(() =>
13 | {
14 | Assert.That(converter.Convert(new object(), null, null, null), Is.EqualTo(true));
15 | Assert.That(converter.Convert(1, null, null, null), Is.EqualTo(true));
16 | });
17 | }
18 |
19 | [Test]
20 | public void Convert_Should_Return_False_Null()
21 | {
22 | var converter = new IsNotNull();
23 |
24 | Assert.That(converter.Convert(null, null, null, null), Is.EqualTo(false));
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Tests/IsNotTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Tests
4 | {
5 | public sealed class IsNotTests
6 | {
7 | [Test]
8 | public void Convert_Should_Return_False_For_Unsupported_DataType()
9 | {
10 | var converter = new IsNot();
11 |
12 | Assert.Multiple(() =>
13 | {
14 | Assert.That(converter.Convert(new object(), null, null, null), Is.EqualTo(false));
15 | Assert.That(converter.Convert(null, null, null, null), Is.EqualTo(false));
16 | Assert.That(converter.Convert(1, null, null, null), Is.EqualTo(false));
17 | });
18 | }
19 |
20 | [Test]
21 | public void Convert_Should_Return_True_For_False()
22 | {
23 | var converter = new IsNot();
24 |
25 | Assert.That(converter.Convert(false, null, null, null), Is.EqualTo(true));
26 | }
27 |
28 | [Test]
29 | public void Convert_Should_Return_False_For_True()
30 | {
31 | var converter = new IsNot();
32 |
33 | Assert.That(converter.Convert(false, null, null, null), Is.EqualTo(true));
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Tests/IsNullOrEmptyTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Tests
4 | {
5 | public sealed class IsNullOrEmptyTests
6 | {
7 | [Test]
8 | public void Convert_Should_Return_False_For_Unsupported_DataType()
9 | {
10 | var converter = new IsNullOrEmpty();
11 |
12 | Assert.Multiple(() =>
13 | {
14 | Assert.That(converter.Convert(new object(), null, null, null), Is.EqualTo(false));
15 | Assert.That(converter.Convert(1, null, null, null), Is.EqualTo(false));
16 | Assert.That(converter.Convert("not null", null, null, null), Is.EqualTo(false));
17 | });
18 | }
19 |
20 | [Test]
21 | public void Convert_Should_Return_True_For_NullOrEmpty()
22 | {
23 | var converter = new IsNullOrEmpty();
24 |
25 | Assert.Multiple(() =>
26 | {
27 | Assert.That(converter.Convert(null, null, null, null), Is.EqualTo(true));
28 | Assert.That(converter.Convert(string.Empty, null, null, null), Is.EqualTo(true));
29 | });
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Tests/IsNullOrWhiteSpaceTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Tests
4 | {
5 | public sealed class IsNullOrWhiteSpaceTests
6 | {
7 | [Test]
8 | public void Convert_Should_Return_False_For_Unsupported_DataType()
9 | {
10 | var converter = new IsNullOrWhiteSpace();
11 |
12 | Assert.Multiple(() =>
13 | {
14 | Assert.That(converter.Convert(new object(), null, null, null), Is.EqualTo(false));
15 | Assert.That(converter.Convert(1, null, null, null), Is.EqualTo(false));
16 | Assert.That(converter.Convert("not null or white space", null, null, null), Is.EqualTo(false));
17 | });
18 | }
19 |
20 | [Test]
21 | public void Convert_Should_Return_True_For_NullOrEmpty()
22 | {
23 | var converter = new IsNullOrWhiteSpace();
24 |
25 | Assert.Multiple(() =>
26 | {
27 | Assert.That(converter.Convert(null, null, null, null), Is.EqualTo(true));
28 | Assert.That(converter.Convert(string.Empty, null, null, null), Is.EqualTo(true));
29 | Assert.That(converter.Convert(" ", null, null, null), Is.EqualTo(true));
30 | });
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Tests/IsNullTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 |
3 | namespace MvvmScarletToolkit.Wpf.Tests
4 | {
5 | public sealed class IsNullTests
6 | {
7 | [Test]
8 | public void Convert_Should_Return_True_For_Anything_But_Null()
9 | {
10 | var converter = new IsNull();
11 |
12 | Assert.Multiple(() =>
13 | {
14 | Assert.That(converter.Convert(new object(), null, null, null), Is.EqualTo(false));
15 | Assert.That(converter.Convert(1, null, null, null), Is.EqualTo(false));
16 | });
17 | }
18 |
19 | [Test]
20 | public void Convert_Should_Return_False_Null()
21 | {
22 | var converter = new IsNull();
23 |
24 | Assert.That(converter.Convert(null, null, null, null), Is.EqualTo(true));
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Tests/MvvmScarletToolkit.Wpf.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0-windows;net9.0-windows
4 | false
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | all
17 | runtime; build; native; contentfiles; analyzers
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | #if NET5_0_OR_GREATER
5 | [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows7.0")]
6 | #endif
7 |
8 | // General Information about an assembly is controlled through the following
9 | // set of attributes. Change these attribute values to modify the information
10 | // associated with an assembly.
11 | [assembly: AssemblyTitle("MvvmScarletToolkit.Wpf.Tests")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // The following GUID is for the ID of the typelib if this project is exposed to COM
17 | [assembly: Guid("b64b25eb-275b-4fbb-98a1-88c4f0035642")]
18 |
--------------------------------------------------------------------------------
/src/MvvmScarletToolkit.Wpf.Tests/TestData/DerivedObjectViewModelBase.cs:
--------------------------------------------------------------------------------
1 | using MvvmScarletToolkit.Observables;
2 |
3 | namespace MvvmScarletToolkit.Tests
4 | {
5 | internal sealed class DerivedObjectViewModelBase : ViewModelBase