diff --git a/.idea/.idea.PSCHelpdesk/.idea/workspace.xml b/.idea/.idea.PSCHelpdesk/.idea/workspace.xml index 42d0573..54edc83 100644 --- a/.idea/.idea.PSCHelpdesk/.idea/workspace.xml +++ b/.idea/.idea.PSCHelpdesk/.idea/workspace.xml @@ -11,612 +11,37 @@ - + + + + - + + + - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + @@ -636,15 +61,26 @@ + + + + + + + + + + + @@ -849,7 +285,10 @@ - + + + + - @@ -896,9 +343,9 @@ @@ -1001,95 +448,17 @@ diff --git a/FastBill/ViewModels/CustomerViewModel.cs b/FastBill/ViewModels/CustomerViewModel.cs index dd95c73..17a19f4 100644 --- a/FastBill/ViewModels/CustomerViewModel.cs +++ b/FastBill/ViewModels/CustomerViewModel.cs @@ -36,6 +36,7 @@ public class CustomerViewModel: ViewModelBase, IViewModelBase public CustomerViewModel(CustomerService customerService) { + Title = "Kunden"; Term = ""; _customerService = customerService; SearchCustomer = ReactiveCommand.Create(searchTerm); diff --git a/HetznerServer/Service/ServerService.cs b/HetznerServer/Service/ServerService.cs index 19da153..c4407fc 100644 --- a/HetznerServer/Service/ServerService.cs +++ b/HetznerServer/Service/ServerService.cs @@ -37,8 +37,8 @@ public class ServerService: IServerService }; _reloadTimer.Interval = TimeSpan.FromMinutes(10); _reloadTimer.Start(); - - this.reloadServer(); + + reloadServer(); } private async Task reloadServer() @@ -61,7 +61,7 @@ public class ServerService: IServerService } } - Task.Run(async () => await this.reloadServerStatus()); + await Task.Run(async () => await this.reloadServerStatus()); } private async Task reloadServerStatus() diff --git a/HetznerServer/ViewModels/ServerViewModel.cs b/HetznerServer/ViewModels/ServerViewModel.cs index b388f0d..286c3d0 100644 --- a/HetznerServer/ViewModels/ServerViewModel.cs +++ b/HetznerServer/ViewModels/ServerViewModel.cs @@ -7,6 +7,7 @@ using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using DynamicData; using DynamicData.Binding; +using Newtonsoft.Json; using PSCHelpdesk.Plugins.HetznerServer.Models; using PSCHelpdesk.Plugins.HetznerServer.Service; using PSCHelpdesk.Plugins.HetznerServer.Views; @@ -17,6 +18,24 @@ using ReactiveUI; namespace PSCHelpdesk.Plugins.HetznerServer.ViewModels; +public class Domain +{ + public string DomainName { get; set; } = string.Empty; +} + +public class Customer +{ + public string Ip4 { get; set; } = string.Empty; + public string ApiKey { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public List Domains { get; set; } = new List(); +} + +public class Customers +{ + public List Data { get; set; } = new List(); +} + public partial class ServerViewModel : ViewModelBase, IViewModelBase { public readonly ServerService ServerService; @@ -29,6 +48,7 @@ public partial class ServerViewModel : ViewModelBase, IViewModelBase private SettingsManager _settingsManager; public ServerViewModel() { + Title = "Server"; ServerService = new ServerService(); SelectedServer = new Server(1,"","","","",""); SelectionChanged = ReactiveCommand.Create(selectionChanged); @@ -69,12 +89,36 @@ public partial class ServerViewModel : ViewModelBase, IViewModelBase set => SetAndRaisePropertyChanged(ref _selectedServer, value); } - + private string _json; + public string Json + { + get => _json; + set => SetAndRaisePropertyChanged(ref _json, value); + } void selectionChanged(SelectionChangedEventArgs args) { this.SelectedServer = (args.Source as DataGrid).SelectedItem as Server; IsPagePaneOpen = true; + + var data = new Customers(); + foreach (var server in _server) + { + var customer = new Customer(); + customer.Name = server.Name; + customer.Ip4 = server.Ipv4; + customer.ApiKey = server.PscApiKey; + foreach (var domain in server.Domains) + { + customer.Domains.Add(new Domain() + { + DomainName = domain.Name + }); + } + data.Data.Add(customer); + } + + Json = JsonConvert.SerializeObject(data); } public void SSH(Server server) @@ -88,11 +132,6 @@ public partial class ServerViewModel : ViewModelBase, IViewModelBase Process.Start(_settingsManager.CoreSettings.SCPClientExecutable,string.Format(_settingsManager.CoreSettings.SCPClientExecutableArgs, server.Ipv4, _settingsManager.CoreSettings.PrivateSSHKeyPath, server.Name)); } - - public UserControl GetViewControl() - { - return new ServerView(); - } void saveServerSettings() { diff --git a/HetznerServer/Views/ServerView.axaml b/HetznerServer/Views/ServerView.axaml index b06163d..bb63366 100644 --- a/HetznerServer/Views/ServerView.axaml +++ b/HetznerServer/Views/ServerView.axaml @@ -18,12 +18,13 @@ - + Suchtext - + + diff --git a/Nextcloud/ViewModels/NotesViewModel.cs b/Nextcloud/ViewModels/NotesViewModel.cs index 93db0c6..2432fa7 100644 --- a/Nextcloud/ViewModels/NotesViewModel.cs +++ b/Nextcloud/ViewModels/NotesViewModel.cs @@ -31,6 +31,7 @@ public partial class NotesViewModel: ViewModelBase, IViewModelBase public NotesViewModel(NotesService notesService) { + Title = "Notes"; SelectedNote = new Note(); Notes = new List(); _notesService = notesService; diff --git a/PSCHelpdesk.sln.DotSettings.user b/PSCHelpdesk.sln.DotSettings.user index 288e94e..34e8340 100644 --- a/PSCHelpdesk.sln.DotSettings.user +++ b/PSCHelpdesk.sln.DotSettings.user @@ -1,6 +1,7 @@  ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -21,10 +22,13 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded + ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -33,6 +37,8 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -43,6 +49,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -58,6 +65,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -91,6 +99,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded True <AssemblyExplorer> diff --git a/PSCHelpdesk/PSCHelpdesk/App.axaml b/PSCHelpdesk/PSCHelpdesk/App.axaml index 335f8a1..0f63236 100644 --- a/PSCHelpdesk/PSCHelpdesk/App.axaml +++ b/PSCHelpdesk/PSCHelpdesk/App.axaml @@ -10,13 +10,14 @@ + + + + + - - - - \ No newline at end of file diff --git a/PSCHelpdesk/PSCHelpdesk/App.axaml.cs b/PSCHelpdesk/PSCHelpdesk/App.axaml.cs index d9819f9..5ff09c0 100644 --- a/PSCHelpdesk/PSCHelpdesk/App.axaml.cs +++ b/PSCHelpdesk/PSCHelpdesk/App.axaml.cs @@ -1,10 +1,7 @@ using Avalonia; using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Data.Core; using Avalonia.Data.Core.Plugins; using Avalonia.Markup.Xaml; -using CommunityToolkit.Mvvm.DependencyInjection; -using NP.Ava.UniDockService; using PSCHelpdesk.ViewModels; using PSCHelpdesk.Views; diff --git a/PSCHelpdesk/PSCHelpdesk/Events/OpenEventArg.cs b/PSCHelpdesk/PSCHelpdesk/Events/OpenEventArg.cs index 6ff738f..c703d91 100644 --- a/PSCHelpdesk/PSCHelpdesk/Events/OpenEventArg.cs +++ b/PSCHelpdesk/PSCHelpdesk/Events/OpenEventArg.cs @@ -1,8 +1,6 @@ -using NP.Ava.UniDockService; - -namespace PSCHelpdesk.Events; +namespace PSCHelpdesk.Events; public class OpenEventArg { - public DockItemViewModelBase Sender; + public string Sender; } \ No newline at end of file diff --git a/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj b/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj index 115596d..3088cf0 100644 --- a/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj +++ b/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj @@ -19,10 +19,12 @@ + + + - @@ -49,10 +51,6 @@ MenuItem.axaml Code - - TestTemplateControl.axaml - Code - @@ -61,5 +59,7 @@ + + diff --git a/PSCHelpdesk/PSCHelpdesk/Startup.cs b/PSCHelpdesk/PSCHelpdesk/Startup.cs index a07b974..18ea4e9 100644 --- a/PSCHelpdesk/PSCHelpdesk/Startup.cs +++ b/PSCHelpdesk/PSCHelpdesk/Startup.cs @@ -1,8 +1,5 @@ using CommunityToolkit.Mvvm.DependencyInjection; using Microsoft.Extensions.DependencyInjection; -using NP.Ava.UniDock; -using NP.Ava.UniDock.Factories; -using NP.Ava.UniDockService; using PSCHelpdesk.Services; using PSCHelpdesk.Shared.Service; using PSCHelpdesk.Shared.Setting; @@ -16,9 +13,6 @@ namespace PSCHelpdesk; class Startup { - - public static DockManager TheDockManager { get; } = new DockManager(); - public static void RegisterServices() { var menuService = new MenuService(); @@ -33,12 +27,9 @@ class Startup .AddSingleton(settingsManager) .AddSingleton(settingsService) .AddSingleton(taskManager) - .AddSingleton() .AddSingleton(menuService) .AddSingleton(new TestService()) .AddSingleton() - .AddSingleton(TheDockManager) - .AddSingleton(TheDockManager) .AddSingleton(toastManager) .AddTransient(); diff --git a/PSCHelpdesk/PSCHelpdesk/ViewModels/DockFactory.cs b/PSCHelpdesk/PSCHelpdesk/ViewModels/DockFactory.cs new file mode 100644 index 0000000..206b21a --- /dev/null +++ b/PSCHelpdesk/PSCHelpdesk/ViewModels/DockFactory.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Dock.Avalonia.Controls; +using Dock.Model.Controls; +using Dock.Model.Core; +using Dock.Model.Mvvm; +using Dock.Model.Mvvm.Controls; + +namespace PSCHelpdesk.ViewModels; + +public class DockFactory : Factory +{ + private IRootDock? _rootDock; + private IDocumentDock? _documentDock; + private ITool? _findTool; + private ITool? _replaceTool; + + public override IDocumentDock CreateDocumentDock() => new DocumentDock(); + + public override IRootDock CreateLayout() + { + + var pluginViewModel = new PluginListViewModel() + { + Title = "Plugins", + }; + + var documentDock = new DocumentDock() + { + Id = "Files", + Title = "Files", + IsCollapsable = false, + //ActiveDockable = pluginViewModel, + Proportion = double.NaN, + VisibleDockables = CreateList + ( + //pluginViewModel + ), + CanCreateDocument = false + }; + + var windowLayout = CreateRootDock(); + windowLayout.Title = "Default"; + var windowLayoutContent = new ProportionalDock + { + Orientation = Orientation.Horizontal, + IsCollapsable = false, + VisibleDockables = CreateList + ( + documentDock + ) + }; + windowLayout.IsCollapsable = false; + windowLayout.VisibleDockables = CreateList(windowLayoutContent); + windowLayout.ActiveDockable = windowLayoutContent; + + var rootDock = CreateRootDock(); + + rootDock.IsCollapsable = false; + rootDock.VisibleDockables = CreateList(windowLayout); + rootDock.ActiveDockable = windowLayout; + rootDock.DefaultDockable = windowLayout; + + _documentDock = documentDock; + _rootDock = rootDock; + + return rootDock; + } + + public override void InitLayout(IDockable layout) + { + DockableLocator = new Dictionary> + { + ["Root"] = () => _rootDock, + ["Files"] = () => _documentDock, + }; + + HostWindowLocator = new Dictionary> + { + [nameof(IDockWindow)] = () => new HostWindow() + }; + + base.InitLayout(layout); + } +} \ No newline at end of file diff --git a/PSCHelpdesk/PSCHelpdesk/ViewModels/MainDockWindowViewModel.cs b/PSCHelpdesk/PSCHelpdesk/ViewModels/MainDockWindowViewModel.cs index 0eb36b6..bde6ca5 100644 --- a/PSCHelpdesk/PSCHelpdesk/ViewModels/MainDockWindowViewModel.cs +++ b/PSCHelpdesk/PSCHelpdesk/ViewModels/MainDockWindowViewModel.cs @@ -1,26 +1,28 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Linq; using System.Reactive; -using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.DependencyInjection; -using NP.Ava.UniDock; -using NP.Ava.UniDockService; +using Dock.Model.Controls; +using Dock.Model.Core; using PSCHelpdesk.Events; using PSCHelpdesk.Services; using PSCHelpdesk.Shared.Menu; using PSCHelpdesk.Shared.Service; -using PSCHelpdesk.Shared.Tasks; using PSCHelpdesk.Shared.ViewModels; -using PSCHelpdesk.Tasks; -using PSCHelpdesk.Toasts.Display; using ReactiveUI; namespace PSCHelpdesk.ViewModels; public class MainDockWindowViewModel : ViewModelBase, IViewModelBase { + private readonly IFactory? _factory; + private IRootDock? _layout; + public IRootDock? Layout + { + get => _layout; + set => SetAndRaisePropertyChanged(ref _layout, value); + } private MenuService MenuService; @@ -70,46 +72,49 @@ public class MainDockWindowViewModel : ViewModelBase, IViewModelBase } }; + _factory = new DockFactory(); this.InitializeClient(); } private void InitializeClient() { + Layout = _factory?.CreateLayout(); + if (Layout is { }) + { + _factory?.InitLayout(Layout); + } + this.MenuService.CreateMenu(); } public void SelectMenu(string parameter) { - var obj = this.MenuService.MenuItems.FirstOrDefault(menuItem => menuItem.Header == parameter.ToString(), null); + var obj = MenuItems.FirstOrDefault(menuItem => menuItem.Header == parameter.ToString(), null); if (obj != null) { - this.openTab?.Invoke(this, new OpenEventArg() + var files = _factory?.GetDockable("Files"); + if (Layout is { } && files is { }) { - Sender = new DockItemViewModelBase() - { - DockId = obj.Header, - Header = obj.Header, - DefaultDockGroupId = "Tabs", - Content = obj.CommandParameter - } - - }); + _factory?.AddDockable(files, (IDocument)obj.CommandParameter); + _factory?.SetActiveDockable((IDocument)obj.CommandParameter); + _factory?.SetFocusedDockable(Layout, (IDocument)obj.CommandParameter); + } } } void openPlugins() { - this.openTab?.Invoke(this, new OpenEventArg() + var pluginM = new PluginListViewModel() { - Sender = new DockItemViewModelBase() - { - DockId = "plugins", - Header = "Plugins", - DefaultDockGroupId = "Tabs", - Content = new PluginListViewModel() - } - - }); + Title = "Plugins", + }; + var files = _factory?.GetDockable("Files"); + if (Layout is { } && files is { }) + { + _factory?.AddDockable(files, pluginM); + _factory?.SetActiveDockable(pluginM); + _factory?.SetFocusedDockable(Layout, pluginM); + } } void loadLayout() diff --git a/PSCHelpdesk/PSCHelpdesk/ViewModels/PluginListViewModel.cs b/PSCHelpdesk/PSCHelpdesk/ViewModels/PluginListViewModel.cs index 3668465..092bf78 100644 --- a/PSCHelpdesk/PSCHelpdesk/ViewModels/PluginListViewModel.cs +++ b/PSCHelpdesk/PSCHelpdesk/ViewModels/PluginListViewModel.cs @@ -2,7 +2,6 @@ using Avalonia.Collections; using Avalonia.Controls; using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; -using NP.Ava.UniDockService; using PSCHelpdesk.Services; using PSCHelpdesk.Shared.ViewModels; @@ -18,6 +17,7 @@ public class PluginListViewModel : ViewModelBase, IViewModelBase public PluginListViewModel() { + Title = "Plugin List"; var pluginService = Ioc.Default.GetService(); this.Plugins = new AvaloniaList(); diff --git a/PSCHelpdesk/PSCHelpdesk/ViewModels/TestTemplateViewModel.cs b/PSCHelpdesk/PSCHelpdesk/ViewModels/TestTemplateViewModel.cs deleted file mode 100644 index c143fb6..0000000 --- a/PSCHelpdesk/PSCHelpdesk/ViewModels/TestTemplateViewModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -using PSCHelpdesk.Shared.ViewModels; - -namespace PSCHelpdesk.ViewModels; - -public class TestTemplateViewModel: ViewModelBase, IViewModelBase -{ - -} \ No newline at end of file diff --git a/PSCHelpdesk/PSCHelpdesk/ViewModels/TestViewModel.cs b/PSCHelpdesk/PSCHelpdesk/ViewModels/TestViewModel.cs deleted file mode 100644 index 7974de0..0000000 --- a/PSCHelpdesk/PSCHelpdesk/ViewModels/TestViewModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -using PSCHelpdesk.Shared.ViewModels; - -namespace PSCHelpdesk.ViewModels; - -public class TestViewModel: ViewModelBase, IViewModelBase -{ - -} \ No newline at end of file diff --git a/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml b/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml index 82ab6e2..713a03c 100644 --- a/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml +++ b/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml @@ -10,19 +10,10 @@ x:Class="PSCHelpdesk.Views.MainDockWindow" Icon="/Assets/avalonia-logo.ico" xmlns:np="https://np.com/visuals" - xmlns:uniDockService="clr-namespace:NP.Ava.UniDockService;assembly=NP.Ava.UniDockService" - np:DockAttachedProperties.TheDockManager="{DynamicResource TheDockManager}" x:DataType="vm:MainDockWindowViewModel" Title="PSCHelpdesk" x:Name="MainWindowView"> - - - - - - - @@ -46,17 +37,6 @@ - - - - - - - - + diff --git a/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs b/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs index 3af7119..5598bf4 100644 --- a/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs +++ b/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs @@ -1,16 +1,11 @@ -using System; -using System.Collections.ObjectModel; -using System.IO; -using System.Linq; -using Avalonia; +using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; using CommunityToolkit.Mvvm.DependencyInjection; -using DynamicData; -using NP.Ava.UniDock; -using NP.Ava.UniDockService; -using NP.Utilities; +using Dock.Avalonia.Controls; +using Dock.Model; +using Dock.Model.Core; +using Dock.Serializer; using PSCHelpdesk.Shared.Service; using PSCHelpdesk.Shared.Setting; using PSCHelpdesk.ViewModels; @@ -19,60 +14,57 @@ namespace PSCHelpdesk.Views; public partial class MainDockWindow : Window { - private DockManager _dockManager; - public IUniDockService _uniDockService; + + private readonly IDockState _dockState; + private readonly IDockSerializer _serializer; + public MainDockWindow() { + _serializer = new DockSerializer(typeof(AvaloniaList<>)); this.DataContext = new MainDockWindowViewModel(); InitializeComponent(); - _dockManager = (DockManager) this.FindResource("TheDockManager")!; - _uniDockService = (IUniDockService)_dockManager!; - - _uniDockService.DockItemsViewModels = - new ObservableCollection(); + + _dockState = new DockState(); + if (Dock is { }) + { + var layout = Dock.Layout; + if (layout is { }) + { + _dockState.Save(layout); + } + } + (this.DataContext as MainDockWindowViewModel).openTab += (_, e) => { - _uniDockService.DockItemsViewModels.Add - ( - e.Sender as DockItemViewModelBase - ); + }; (this.DataContext as MainDockWindowViewModel).SaveHandler += (_, __) => { var settingsManager = (SettingsManager)Ioc.Default.GetService(); - _uniDockService.SaveToFile(Path.Combine(settingsManager.DataRoot, "DockSerialization.xml")); - - - foreach (var docItem in _uniDockService.DockItemsViewModels) + var dock = this.FindControl("Dock"); + if (dock?.Layout is { }) { - + settingsManager.SaveLayoutModels(_serializer.Serialize(dock.Layout)); } - - //_uniDockService.SaveViewModelsToFile(Path.Combine(settingsManager.DataRoot, "DockVMSerialization.xml")); }; (this.DataContext as MainDockWindowViewModel).LoadHandler += (_, __) => { var settingsManager = (SettingsManager)Ioc.Default.GetService(); - //_uniDockService.DockItemsViewModels = null; - - _dockManager.RestoreFromFile(Path.Combine(settingsManager.DataRoot, "DockSerialization.xml")); - var viewLocator = new ViewLocator(); - foreach (var docItem in _dockManager.ConnectedGroups.NullToEmpty().Where(e => e is DockItem)) + var dock = this.FindControl("Dock"); + if (dock is { }) { - Console.WriteLine(docItem); + var layout = _serializer.Deserialize(settingsManager.LoadLayoutModels()); + + if (layout is { }) + { + dock.Layout = layout; + _dockState.Restore(layout); + } } - _dockManager.DockItemsViewModels.Add(new DockItemViewModelBase() - { - DockId = "plugins", - Header = "Plugins", - DefaultDockGroupId = "Tabs", - Content = new PluginListViewModel() - }); - _dockManager.DockItemsViewModels?.OfType().FirstOrDefault()?.Select(); }; } diff --git a/PSCHelpdesk/PSCHelpdesk/Views/TestListView.axaml b/PSCHelpdesk/PSCHelpdesk/Views/TestListView.axaml deleted file mode 100644 index 4f62d85..0000000 --- a/PSCHelpdesk/PSCHelpdesk/Views/TestListView.axaml +++ /dev/null @@ -1,10 +0,0 @@ - - Welcome to Avalonia! - diff --git a/PSCHelpdesk/PSCHelpdesk/Views/TestListView.axaml.cs b/PSCHelpdesk/PSCHelpdesk/Views/TestListView.axaml.cs deleted file mode 100644 index 014ee2e..0000000 --- a/PSCHelpdesk/PSCHelpdesk/Views/TestListView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Markup.Xaml; - -namespace PSCHelpdesk.Views; - -public partial class TestListView : UserControl -{ - public TestListView() - { - InitializeComponent(); - } -} \ No newline at end of file diff --git a/PSCHelpdesk/PSCHelpdesk/Views/TestTemplateView.axaml b/PSCHelpdesk/PSCHelpdesk/Views/TestTemplateView.axaml deleted file mode 100644 index 36091bf..0000000 --- a/PSCHelpdesk/PSCHelpdesk/Views/TestTemplateView.axaml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/PSCHelpdesk/PSCHelpdesk/Views/TestTemplateView.axaml.cs b/PSCHelpdesk/PSCHelpdesk/Views/TestTemplateView.axaml.cs deleted file mode 100644 index ba5ab37..0000000 --- a/PSCHelpdesk/PSCHelpdesk/Views/TestTemplateView.axaml.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.Primitives; - -namespace PSCHelpdesk.Views; - -public class TestTemplateView : TemplatedControl -{ -} \ No newline at end of file diff --git a/Shared/Model/LayoutItem.cs b/Shared/Model/LayoutItem.cs new file mode 100644 index 0000000..6440e12 --- /dev/null +++ b/Shared/Model/LayoutItem.cs @@ -0,0 +1,11 @@ +using System; + +namespace PSCHelpdesk.Shared.Model; + +public class LayoutItem +{ + public string DockId { get; set; } + public string Header { get; set; } + public string DefaultDockGroupId { get; set; } + public string Content { get; set; } +} \ No newline at end of file diff --git a/Shared/Setting/SettingsManager.cs b/Shared/Setting/SettingsManager.cs index ebc3452..4bd3a16 100644 --- a/Shared/Setting/SettingsManager.cs +++ b/Shared/Setting/SettingsManager.cs @@ -1,4 +1,6 @@ +using Dock.Model.Core; using Newtonsoft.Json; +using PSCHelpdesk.Shared.Model; using PSCHelpdesk.Shared.Service; namespace PSCHelpdesk.Shared.Setting; @@ -86,4 +88,22 @@ public class SettingsManager: ISettingsManager serializer.Serialize(file, settingsObject); } } + + public void SaveLayoutModels(string data) + { + var settingsPath = Path.Combine(this.DataRoot, "layout_settings.json"); + + using (StreamWriter file = File.CreateText(settingsPath)) + { + file.Write(data); + } + } + + public string LoadLayoutModels() + { + var settingsPath = Path.Combine(this.DataRoot, "layout_settings.json"); + var layoutModels = File.ReadAllText(settingsPath); + + return layoutModels; + } } diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj index 3d820e1..bcd6c86 100644 --- a/Shared/Shared.csproj +++ b/Shared/Shared.csproj @@ -27,7 +27,7 @@ - + diff --git a/Shared/ViewModels/ViewModelBase.cs b/Shared/ViewModels/ViewModelBase.cs index ae3445c..630db5f 100644 --- a/Shared/ViewModels/ViewModelBase.cs +++ b/Shared/ViewModels/ViewModelBase.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; -using NP.Ava.UniDockService; -using NP.Utilities; +using Dock.Model.Mvvm.Controls; namespace PSCHelpdesk.Shared.ViewModels; -public class ViewModelBase : INotifyPropertyChanged +public class ViewModelBase : Document, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; diff --git a/_dist/hetzner/HetznerServer.deps.json b/_dist/hetzner/HetznerServer.deps.json index d9eb5a1..a0d31b1 100644 --- a/_dist/hetzner/HetznerServer.deps.json +++ b/_dist/hetzner/HetznerServer.deps.json @@ -77,6 +77,14 @@ } }, "Avalonia.BuildServices/0.0.29": {}, + "Avalonia.Controls.Recycling.Model/11.2.0": { + "runtime": { + "lib/net8.0/Avalonia.Controls.Recycling.Model.dll": { + "assemblyVersion": "11.2.0.0", + "fileVersion": "11.2.0.0" + } + } + }, "Avalonia.ReactiveUI/11.2.0": { "dependencies": { "Avalonia": "11.2.0", @@ -202,6 +210,29 @@ } } }, + "Dock.Model/11.2.0": { + "dependencies": { + "Avalonia.Controls.Recycling.Model": "11.2.0" + }, + "runtime": { + "lib/net8.0/Dock.Model.dll": { + "assemblyVersion": "11.2.0.0", + "fileVersion": "11.2.0.0" + } + } + }, + "Dock.Model.Mvvm/11.2.0": { + "dependencies": { + "CommunityToolkit.Mvvm": "8.3.2", + "Dock.Model": "11.2.0" + }, + "runtime": { + "lib/net8.0/Dock.Model.Mvvm.dll": { + "assemblyVersion": "11.2.0.0", + "fileVersion": "11.2.0.0" + } + } + }, "DynamicData/8.4.1": { "dependencies": { "System.Reactive": "6.0.1" @@ -279,25 +310,6 @@ } } }, - "NP.Ava.UniDockService/1.0.6": { - "dependencies": { - "NP.Utilities": "1.0.30" - }, - "runtime": { - "lib/net8.0/NP.Ava.UniDockService.dll": { - "assemblyVersion": "1.0.6.0", - "fileVersion": "1.0.6.0" - } - } - }, - "NP.Utilities/1.0.30": { - "runtime": { - "lib/net8.0/NP.Utilities.dll": { - "assemblyVersion": "1.0.30.0", - "fileVersion": "1.0.30.0" - } - } - }, "ReactiveUI/20.1.1": { "dependencies": { "DynamicData": "8.4.1", @@ -358,6 +370,13 @@ "path": "avalonia.buildservices/0.0.29", "hashPath": "avalonia.buildservices.0.0.29.nupkg.sha512" }, + "Avalonia.Controls.Recycling.Model/11.2.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-QSvLVBhBWGZvmX4dZu5gNaTHfOkh+CtwT2fvM1WnroG2zKdpev00M3U+/x+o9wuWR+FDFodqfIsDHU/s3w6Q1A==", + "path": "avalonia.controls.recycling.model/11.2.0", + "hashPath": "avalonia.controls.recycling.model.11.2.0.nupkg.sha512" + }, "Avalonia.ReactiveUI/11.2.0": { "type": "package", "serviceable": true, @@ -435,6 +454,20 @@ "path": "communitytoolkit.mvvm/8.3.2", "hashPath": "communitytoolkit.mvvm.8.3.2.nupkg.sha512" }, + "Dock.Model/11.2.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-vvgwgCr3IXq3LQQTXiaEeoWPkze31HJxTdEWw8cv84VECHIgH4TiPN1l3P+6u8fKT+4V8cgC1rD8Z4nHUQFkcA==", + "path": "dock.model/11.2.0", + "hashPath": "dock.model.11.2.0.nupkg.sha512" + }, + "Dock.Model.Mvvm/11.2.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-XbE5W4Dm+YcN5xfKW3V9NyHNiwev3WYlmWdskx5sO2oFMUuVizyWvwz6JyyqjXadI86tVxi+a9DlsyuPkHCNuA==", + "path": "dock.model.mvvm/11.2.0", + "hashPath": "dock.model.mvvm.11.2.0.nupkg.sha512" + }, "DynamicData/8.4.1": { "type": "package", "serviceable": true, @@ -491,20 +524,6 @@ "path": "newtonsoft.json/13.0.3", "hashPath": "newtonsoft.json.13.0.3.nupkg.sha512" }, - "NP.Ava.UniDockService/1.0.6": { - "type": "package", - "serviceable": true, - "sha512": "sha512-GHS67athB7fd/qvHJOEbYJUtJjKjjqf0sVcF1iB0CxqNrKgG5LPGzGyCdynYsy+gi7SqO29S+eqQK+3E9D7Mrw==", - "path": "np.ava.unidockservice/1.0.6", - "hashPath": "np.ava.unidockservice.1.0.6.nupkg.sha512" - }, - "NP.Utilities/1.0.30": { - "type": "package", - "serviceable": true, - "sha512": "sha512-yNvPMvlhuh8oYt9qYOoGC650uhe/lSleKI6RV7hEOyLWiah8NgPXwdj2GquR9ySCtWefjPkHYwTUDRwP0hw0ZQ==", - "path": "np.utilities/1.0.30", - "hashPath": "np.utilities.1.0.30.nupkg.sha512" - }, "ReactiveUI/20.1.1": { "type": "package", "serviceable": true, diff --git a/_dist/hetzner/HetznerServer.dll b/_dist/hetzner/HetznerServer.dll index 914aae5..22965a4 100644 Binary files a/_dist/hetzner/HetznerServer.dll and b/_dist/hetzner/HetznerServer.dll differ diff --git a/_dist/hetzner/HetznerServer.pdb b/_dist/hetzner/HetznerServer.pdb index 4653c08..ba54c1f 100644 Binary files a/_dist/hetzner/HetznerServer.pdb and b/_dist/hetzner/HetznerServer.pdb differ diff --git a/_dist/nextcloud/CommunityToolkit.Mvvm.pdb b/_dist/nextcloud/CommunityToolkit.Mvvm.pdb deleted file mode 100755 index b782501..0000000 Binary files a/_dist/nextcloud/CommunityToolkit.Mvvm.pdb and /dev/null differ diff --git a/_dist/nextcloud/CommunityToolkit.Mvvm.xml b/_dist/nextcloud/CommunityToolkit.Mvvm.xml deleted file mode 100755 index 63cfd9d..0000000 --- a/_dist/nextcloud/CommunityToolkit.Mvvm.xml +++ /dev/null @@ -1,4490 +0,0 @@ - - - - CommunityToolkit.Mvvm - - - - - A helper type for the type. - - - - - The cached for - - - - - An interface for a grouped collection of items. - - - - - Gets the key for the current collection. - - - - - Gets the number of items currently in the grouped collection. - - - - - Gets the element at the specified index in the current collection. - - The zero-based index of the element to get. - The element at the specified index in the read-only list. - Thrown if the index is out of range. - - - - An interface for a grouped collection of items. - - The type of the group key. - The type of elements in the group. - - - - Gets the element at the specified index in the current collection. - - The zero-based index of the element to get. - The element at the specified index in the read-only list. - Thrown if the index is out of range. - - - - An interface for a grouped collection of items. - - The type of the group key. - - - - Gets the key for the current collection. - - - - - The extensions methods to simplify the usage of . - - - - - Returns the first group with key. - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group to query. - The first group matching . - Thrown if or are . - The target group does not exist. - - - - Returns the first group with key or if not found. - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group to query. - The first group matching or . - Thrown if or are . - - - - Adds a key-value item into a target . - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group to add. - The added . - Thrown if or are . - - - - Adds a key-collection item into a target . - - The type of the group key. - The type of the items in the collection. - The source instance. - The group of items to add. - The added . - Thrown if or are . - - - - Adds a key-collection item into a target . - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group where will be added. - The collection to add. - The added . - Thrown if , or are . - - - - Adds a key-value item into a target . - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group to add. - The added . - Thrown if or are . - - - - Adds a key-value item into a target . - - The type of the group key. - The type of the items in the collection. - The source instance. - The group of items to add. - The added . - Thrown if or are . - - - - Adds a key-value item into a target . - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group where will be added. - The collection to add. - The added . - Thrown if , or are . - - - - Adds a key-value item into a target . - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group to add. - The instance to insert at the right position. - The added . - Thrown if , or are . - - - - Adds a key-value item into a target . - - The type of the group key. - The type of the items in the collection. - The source instance. - The group of items to add. - The instance to insert at the right position. - The added . - Thrown if , or are . - - - - Adds a key-value item into a target . - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group where will be added. - The instance to insert at the right position. - The collection to add. - The added . - Thrown if , , or are . - - - - Add into the first group with key. - If the group does not exist, it will be added. - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group where the should be added. - The item to add. - The instance of the which will receive the value. It will either be an existing group or a new group. - Thrown if or are . - - - - Insert into the first group with key. - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group where to insert . - The item to add. - The instance of the which will receive the value. - Thrown if or are . - - - - Insert into the first group with key. - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group where to insert . - The instance to compare keys. - The item to add. - The instance to compare elements. - The instance of the which will receive the value. - Thrown if , , or are . - - - - Remove the first occurrence of the group with from the grouped collection. - It will not do anything if the group does not exist. - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group to remove. - Thrown if or are . - - - - Remove the first from the first group with from the grouped collection. - It will not do anything if the group or the item does not exist. - - The type of the group key. - The type of the items in the collection. - The source instance. - The key of the group where the should be removed. - The item to remove. - If true (default value), the group will be removed once it becomes empty. - Thrown if or are . - - - - An observable list of observable groups. - - The type of the group keys. - The type of elements in the collection. - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - The initial data to add in the grouped collection. - Thrown if is . - - - - - - - Tries to get the underlying instance, if present. - - The resulting , if one was in use. - Whether or not a instance has been found. - - - - - - - - - - An observable group. - It associates a to an . - - The type of the group key. - The type of elements in the group. - - - - Initializes a new instance of the class. - - The key for the group. - Thrown if is . - - - - Initializes a new instance of the class. - - The grouping to fill the group. - Thrown if is . - - - - Initializes a new instance of the class. - - The key for the group. - The initial collection of data to add to the group. - Thrown if or are . - - - - Gets or sets the key of the group. - - Thrown if is . - - - - Tries to get the underlying instance, if present. - - The resulting , if one was in use. - Whether or not a instance has been found. - - - - - - - - - - A read-only list of groups. - - The type of the group keys. - The type of elements in the collection. - - - - Initializes a new instance of the class. - - The source collection to wrap. - Thrown if is . - - - - Initializes a new instance of the class. - - The source collection to wrap. - Thrown if is . - - - - - - - - - - - - - Forwards the event whenever it is raised by the wrapped collection. - - The wrapped collection (an of instance). - The arguments. - Thrown if a range operation is requested. - - - - Returns the first group with key or if not found. - - The key of the group to query (assumed not to be ). - The first group matching . - - - - A read-only observable group. It associates a to a . - - The type of the group key. - The type of elements in the group. - - - - Initializes a new instance of the class. - - The key of the group. - The collection of items to add in the group. - Thrown if or are . - - - - Initializes a new instance of the class. - - The to wrap. - Thrown if is . - - - - - - - - - - - - - An attribute that indicates that a given type should implement the interface and - have minimal built-in functionality to support it. This includes exposing the necessary event and having two methods - to raise it that mirror and - . For more extensive support, use . - - This attribute can be used as follows: - - [INotifyPropertyChanged] - partial class MyViewModel : SomeOtherClass - { - // Other members here... - } - - - - - - - Gets or sets a value indicating whether or not to also generate all the additional helper methods that are found - in as well (eg. . - If set to , only the event and - the two overloads will be generated. - The default value is . - - - - - An attribute that can be used to support properties in generated properties. When this attribute is - used, the generated property setter will also call for the properties specified - in the attribute data, causing the validation logic for the command to be executed again. This can be useful to keep the code compact - when there are one or more dependent commands that should also be notified when a property is updated. If this attribute is used in - a field without , it is ignored (just like ). - - In order to use this attribute, the target property has to implement the interface. - - - This attribute can be used as follows: - - partial class MyViewModel : ObservableObject - { - [ObservableProperty] - [NotifyCanExecuteChangedFor(nameof(GreetUserCommand))] - private string name; - - public IRelayCommand GreetUserCommand { get; } - } - - - And with this, code analogous to this will be generated: - - partial class MyViewModel - { - public string Name - { - get => name; - set - { - if (SetProperty(ref name, value)) - { - GreetUserCommand.NotifyCanExecuteChanged(); - } - } - } - } - - - - - - Initializes a new instance of the class. - - The name of the command to also notify when the annotated property changes. - - - - Initializes a new instance of the class. - - The name of the property to also notify when the annotated property changes. - - The other command names to also notify when the annotated property changes. This parameter can optionally - be used to indicate a series of dependent commands from the same attribute, to keep the code more compact. - - - - - Gets the command names to also notify when the annotated property changes. - - - - - An attribute that can be used to support in generated properties, when applied to - fields contained in a type that is inheriting from and using any validation attributes. - When this attribute is used, the generated property setter will also call . - This allows generated properties to opt-in into validation behavior without having to fallback into a full explicit observable property. - - This attribute can be used as follows: - - partial class MyViewModel : ObservableValidator - { - [ObservableProperty] - [NotifyDataErrorInfo] - [Required] - [MinLength(2)] - private string username; - } - - - And with this, code analogous to this will be generated: - - partial class MyViewModel - { - [Required] - [MinLength(2)] - public string Username - { - get => username; - set => SetProperty(ref username, value, validate: true); - } - } - - - - - - An attribute that can be used to support in generated properties. When this attribute is - used, the generated property setter will also call (or the equivalent - method in the target class) for the properties specified in the attribute data. This can be useful to keep the code compact when - there are one or more dependent properties that should also be reported as updated when the value of the annotated observable - property is changed. If this attribute is used in a field without , it is ignored. - - In order to use this attribute, the containing type has to implement the interface - and expose a method with the same signature as . If the containing - type also implements the interface and exposes a method with the same signature as - , then this method will be invoked as well by the property setter. - - - This attribute can be used as follows: - - partial class MyViewModel : ObservableObject - { - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(FullName))] - private string name; - - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(FullName))] - private string surname; - - public string FullName => $"{Name} {Surname}"; - } - - - And with this, code analogous to this will be generated: - - partial class MyViewModel - { - public string Name - { - get => name; - set - { - if (!EqualityComparer<string>.Default.Equals(name, value)) - { - OnPropertyChanging(nameof(Name)); - OnPropertyChanged(nameof(FullName)); - - name = value; - - OnPropertyChanged(nameof(Name)); - OnPropertyChanged(nameof(FullName)); - } - } - } - - public string Surname - { - get => surname; - set - { - if (!EqualityComparer<string>.Default.Equals(name, value)) - { - OnPropertyChanging(nameof(Surname)); - OnPropertyChanged(nameof(FullName)); - - surname = value; - - OnPropertyChanged(nameof(Surname)); - OnPropertyChanged(nameof(FullName)); - } - } - } - } - - - - - - Initializes a new instance of the class. - - The name of the property to also notify when the annotated property changes. - - - - Initializes a new instance of the class. - - The name of the property to also notify when the annotated property changes. - - The other property names to also notify when the annotated property changes. This parameter can optionally - be used to indicate a series of dependent properties from the same attribute, to keep the code more compact. - - - - - Gets the property names to also notify when the annotated property changes. - - - - - An attribute that can be used to support in generated properties, when applied to fields - contained in a type that is either inheriting from , or annotated with . - When this attribute is used, the generated property setter will also call . - This allows generated properties to opt-in into broadcasting behavior without having to fallback into a full explicit observable property. - - This attribute can be used as follows: - - partial class MyViewModel : ObservableRecipient - { - [ObservableProperty] - [NotifyPropertyChangedRecipients] - private string username; - } - - - - And with this, code analogous to this will be generated: - - partial class MyViewModel - { - public string Username - { - get => username; - set => SetProperty(ref username, value, broadcast: true); - } - } - - - - This attribute can also be added to a class, and if so it will affect all generated properties in that type and inherited types. - - - - - - An attribute that indicates that a given type should have all the members from - generated into it, as well as the and - interfaces. This can be useful when you want the same functionality from into a class - that already inherits from another one (since C# doesn't support multiple inheritance). This attribute will trigger - the source generator to just create the same APIs directly into the decorated class. - - This attribute can be used as follows: - - [ObservableObject] - partial class MyViewModel : SomeOtherClass - { - // Other members here... - } - - - And with this, the same APIs from will be available on this type as well. - - - - - An attribute that indicates that a given field should be wrapped by a generated observable property. - In order to use this attribute, the containing type has to inherit from , or it - must be using or . - If the containing type also implements the (that is, if it either inherits from - or is using ), then the generated code will - also invoke to signal that event. - - This attribute can be used as follows: - - partial class MyViewModel : ObservableObject - { - [ObservableProperty] - private string name; - - [ObservableProperty] - private bool isEnabled; - } - - - And with this, code analogous to this will be generated: - - partial class MyViewModel - { - public string Name - { - get => name; - set => SetProperty(ref name, value); - } - - public bool IsEnabled - { - get => isEnabled; - set => SetProperty(ref isEnabled, value); - } - } - - - - The generated properties will automatically use the UpperCamelCase format for their names, - which will be derived from the field names. The generator can also recognize fields using either - the _lowerCamel or m_lowerCamel naming scheme. Otherwise, the first character in the - source field name will be converted to uppercase (eg. isEnabled to IsEnabled). - - - - - An attribute that indicates that a given type should have all the members from - generated into it. This can be useful when you want the same functionality from into - a class that already inherits from another one (since C# doesn't support multiple inheritance). This attribute will trigger - the source generator to just create the same APIs directly into the decorated class. For instance, this attribute can be - used to easily combine the functionality from both and , - by using as the base class and adding this attribute to the declared type. - - This attribute can be used as follows: - - [ObservableRecipient] - partial class MyViewModel : ObservableValidator - { - // Other members here... - } - - - And with this, the same APIs from will be available on this type as well. - - To avoid conflicts with other APIs in types where the new members are being generated, constructors are only generated when the annotated - type doesn't have any explicit constructors being declared. If that is the case, the same constructors from - are emitted, with the accessibility adapted to that of the annotated type. Otherwise, they are skipped, so the type being annotated has the - responsibility of properly initializing the property. Additionally, if the annotated type inherits - from , the overloads will be skipped - as well, as they would conflict with the methods. - - - - In order to work, needs to be applied to a type that inherits from - (either directly or indirectly), or to one decorated with . - This is because the methods rely on some of the inherited members to work. - If this condition is not met, the code will fail to build. - - - - - A base class for objects of which the properties must be observable. - - - - - - - - - - - Raises the event. - - The input instance. - Thrown if is . - - - - Raises the event. - - The input instance. - Thrown if is . - - - - Raises the event. - - (optional) The name of the property that changed. - - - - Raises the event. - - (optional) The name of the property that changed. - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with the new - value, then raises the event. - - The type of the property that changed. - The field storing the property's value. - The property's value after the change occurred. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - The and events are not raised - if the current and new value for the target property are the same. - - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with the new - value, then raises the event. - See additional notes about this overload in . - - The type of the property that changed. - The field storing the property's value. - The property's value after the change occurred. - The instance to use to compare the input values. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if is . - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with the new - value, then raises the event. - This overload is much less efficient than and it - should only be used when the former is not viable (eg. when the target property being - updated does not directly expose a backing field that can be passed by reference). - For performance reasons, it is recommended to use a stateful callback if possible through - the whenever possible - instead of this overload, as that will allow the C# compiler to cache the input callback and - reduce the memory allocations. More info on that overload are available in the related XML - docs. This overload is here for completeness and in cases where that is not applicable. - - The type of the property that changed. - The current property value. - The property's value after the change occurred. - A callback to invoke to update the property value. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - The and events are not raised - if the current and new value for the target property are the same. - - Thrown if is . - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with the new - value, then raises the event. - See additional notes about this overload in . - - The type of the property that changed. - The current property value. - The property's value after the change occurred. - The instance to use to compare the input values. - A callback to invoke to update the property value. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if or are . - - - - Compares the current and new values for a given nested property. If the value has changed, - raises the event, updates the property and then raises the - event. The behavior mirrors that of , - with the difference being that this method is used to relay properties from a wrapped model in the - current instance. This type is useful when creating wrapping, bindable objects that operate over - models that lack support for notification (eg. for CRUD operations). - Suppose we have this model (eg. for a database row in a table): - - public class Person - { - public string Name { get; set; } - } - - We can then use a property to wrap instances of this type into our observable model (which supports - notifications), injecting the notification to the properties of that model, like so: - - public class BindablePerson : ObservableObject - { - public Model { get; } - - public BindablePerson(Person model) - { - Model = model; - } - - public string Name - { - get => Model.Name; - set => Set(Model.Name, value, Model, (model, name) => model.Name = name); - } - } - - This way we can then use the wrapping object in our application, and all those "proxy" properties will - also raise notifications when changed. Note that this method is not meant to be a replacement for - , and it should only be used when relaying properties to a model that - doesn't support notifications, and only if you can't implement notifications to that model directly (eg. by having - it inherit from ). The syntax relies on passing the target model and a stateless callback - to allow the C# compiler to cache the function, which results in much better performance and no memory usage. - - The type of model whose property (or field) to set. - The type of property (or field) to set. - The current property value. - The property's value after the change occurred. - The model containing the property being updated. - The callback to invoke to set the target property value, if a change has occurred. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - The and events are not - raised if the current and new value for the target property are the same. - - Thrown if or are . - - - - Compares the current and new values for a given nested property. If the value has changed, - raises the event, updates the property and then raises the - event. The behavior mirrors that of , - with the difference being that this method is used to relay properties from a wrapped model in the - current instance. See additional notes about this overload in . - - The type of model whose property (or field) to set. - The type of property (or field) to set. - The current property value. - The property's value after the change occurred. - The instance to use to compare the input values. - The model containing the property being updated. - The callback to invoke to set the target property value, if a change has occurred. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if , or are . - - - - Compares the current and new values for a given field (which should be the backing - field for a property). If the value has changed, raises the - event, updates the field and then raises the event. - The behavior mirrors that of , with the difference being that - this method will also monitor the new value of the property (a generic ) and will also - raise the again for the target property when it completes. - This can be used to update bindings observing that or any of its properties. - This method and its overload specifically rely on the type, which needs - to be used in the backing field for the target property. The field doesn't need to be - initialized, as this method will take care of doing that automatically. The - type also includes an implicit operator, so it can be assigned to any instance directly. - Here is a sample property declaration using this method: - - private TaskNotifier myTask; - - public Task MyTask - { - get => myTask; - private set => SetAndNotifyOnCompletion(ref myTask, value); - } - - - The field notifier to modify. - The property's value after the change occurred. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - The and events are not raised if the current - and new value for the target property are the same. The return value being only - indicates that the new value being assigned to is different than the previous one, - and it does not mean the new instance passed as argument is in any particular state. - - - - - Compares the current and new values for a given field (which should be the backing - field for a property). If the value has changed, raises the - event, updates the field and then raises the event. - This method is just like , - with the difference being an extra parameter with a callback being invoked - either immediately, if the new task has already completed or is , or upon completion. - - The field notifier to modify. - The property's value after the change occurred. - A callback to invoke to update the property value. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - The and events are not raised - if the current and new value for the target property are the same. - - Thrown if is . - - - - Compares the current and new values for a given field (which should be the backing - field for a property). If the value has changed, raises the - event, updates the field and then raises the event. - The behavior mirrors that of , with the difference being that - this method will also monitor the new value of the property (a generic ) and will also - raise the again for the target property when it completes. - This can be used to update bindings observing that or any of its properties. - This method and its overload specifically rely on the type, which needs - to be used in the backing field for the target property. The field doesn't need to be - initialized, as this method will take care of doing that automatically. The - type also includes an implicit operator, so it can be assigned to any instance directly. - Here is a sample property declaration using this method: - - private TaskNotifier<int> myTask; - - public Task<int> MyTask - { - get => myTask; - private set => SetAndNotifyOnCompletion(ref myTask, value); - } - - - The type of result for the to set and monitor. - The field notifier to modify. - The property's value after the change occurred. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - The and events are not raised if the current - and new value for the target property are the same. The return value being only - indicates that the new value being assigned to is different than the previous one, - and it does not mean the new instance passed as argument is in any particular state. - - - - - Compares the current and new values for a given field (which should be the backing - field for a property). If the value has changed, raises the - event, updates the field and then raises the event. - This method is just like , - with the difference being an extra parameter with a callback being invoked - either immediately, if the new task has already completed or is , or upon completion. - - The type of result for the to set and monitor. - The field notifier to modify. - The property's value after the change occurred. - A callback to invoke to update the property value. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - The and events are not raised - if the current and new value for the target property are the same. - - Thrown if is . - - - - Implements the notification logic for the related methods. - - The type of to set and monitor. - The field notifier. - The property's value after the change occurred. - (optional) A callback to invoke to update the property value. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - - - An interface for task notifiers of a specified type. - - The type of value to store. - - - - Gets or sets the wrapped value. - - - - - A wrapping class that can hold a value. - - - - - Initializes a new instance of the class. - - - - - - - - Unwraps the value stored in the current instance. - - The input instance. - - - - A wrapping class that can hold a value. - - The type of value for the wrapped instance. - - - - Initializes a new instance of the class. - - - - - - - - Unwraps the value stored in the current instance. - - The input instance. - - - - A base class for observable objects that also acts as recipients for messages. This class is an extension of - which also provides built-in support to use the type. - - - - - Initializes a new instance of the class. - - - This constructor will produce an instance that will use the instance - to perform requested operations. It will also be available locally through the property. - - - - - Initializes a new instance of the class. - - The instance to use to send messages. - Thrown if is . - - - - Gets the instance in use. - - - - - Gets or sets a value indicating whether the current view model is currently active. - - - - - Invoked whenever the property is set to . - Use this method to register to messages and do other initialization for this instance. - - - The base implementation registers all messages for this recipients that have been declared - explicitly through the interface, using the default channel. - For more details on how this works, see the method. - If you need more fine tuned control, want to register messages individually or just prefer - the lambda-style syntax for message registration, override this method and register manually. - - - - - Invoked whenever the property is set to . - Use this method to unregister from messages and do general cleanup for this instance. - - - The base implementation unregisters all messages for this recipient. It does so by - invoking , which removes all registered - handlers for a given subscriber, regardless of what token was used to register them. - That is, all registered handlers across all subscription channels will be removed. - - - - - Broadcasts a with the specified - parameters, without using any particular token (so using the default channel). - - The type of the property that changed. - The value of the property before it changed. - The value of the property after it changed. - The name of the property that changed. - - You should override this method if you wish to customize the channel being - used to send the message (eg. if you need to use a specific token for the channel). - - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with - the new value, then raises the event. - - The type of the property that changed. - The field storing the property's value. - The property's value after the change occurred. - If , will also be invoked. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - This method is just like , just with the addition - of the parameter. As such, following the behavior of the base method, - the and events - are not raised if the current and new value for the target property are the same. - - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with - the new value, then raises the event. - See additional notes about this overload in . - - The type of the property that changed. - The field storing the property's value. - The property's value after the change occurred. - The instance to use to compare the input values. - If , will also be invoked. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if is . - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with - the new value, then raises the event. Similarly to - the method, this overload should only be - used when can't be used directly. - - The type of the property that changed. - The current property value. - The property's value after the change occurred. - A callback to invoke to update the property value. - If , will also be invoked. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - This method is just like , just with the addition - of the parameter. As such, following the behavior of the base method, - the and events - are not raised if the current and new value for the target property are the same. - - Thrown if is . - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with - the new value, then raises the event. - See additional notes about this overload in . - - The type of the property that changed. - The current property value. - The property's value after the change occurred. - The instance to use to compare the input values. - A callback to invoke to update the property value. - If , will also be invoked. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if or are . - - - - Compares the current and new values for a given nested property. If the value has changed, - raises the event, updates the property and then raises the - event. The behavior mirrors that of - , with the difference being that this - method is used to relay properties from a wrapped model in the current instance. For more info, see the docs for - . - - The type of model whose property (or field) to set. - The type of property (or field) to set. - The current property value. - The property's value after the change occurred. - The model - The callback to invoke to set the target property value, if a change has occurred. - If , will also be invoked. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if or are . - - - - Compares the current and new values for a given nested property. If the value has changed, - raises the event, updates the property and then raises the - event. The behavior mirrors that of - , - with the difference being that this method is used to relay properties from a wrapped model in the - current instance. For more info, see the docs for - . - - The type of model whose property (or field) to set. - The type of property (or field) to set. - The current property value. - The property's value after the change occurred. - The instance to use to compare the input values. - The model - The callback to invoke to set the target property value, if a change has occurred. - If , will also be invoked. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if , or are . - - - - A base class for objects implementing the interface. This class - also inherits from , so it can be used for observable items too. - - - - - The instance used to track compiled delegates to validate entities. - - - - - The instance used to track display names for properties to validate. - - - This is necessary because we want to reuse the same instance for all validations, but - with the same behavior with respect to formatted names that new instances would have provided. The issue is that the - property is not refreshed when we set , - so we need to replicate the same logic to retrieve the right display name for properties to validate and update that - property manually right before passing the context to and proceed with the normal functionality. - - - - - The cached for . - - - - - The instance currently in use. - - - - - The instance used to store previous validation results. - - - - - Indicates the total number of properties with errors (not total errors). - This is used to allow to operate in O(1) time, as it can just - check whether this value is not 0 instead of having to traverse . - - - - - - - - Initializes a new instance of the class. - This constructor will create a new that will - be used to validate all properties, which will reference the current instance - and no additional services or validation properties and settings. - - - - - Initializes a new instance of the class. - This constructor will create a new that will - be used to validate all properties, which will reference the current instance. - - A set of key/value pairs to make available to consumers. - - - - Initializes a new instance of the class. - This constructor will create a new that will - be used to validate all properties, which will reference the current instance. - - An instance to make available during validation. - A set of key/value pairs to make available to consumers. - - - - Initializes a new instance of the class. - This constructor will store the input instance, - and it will use it to validate all properties for the current viewmodel. - - - The instance to use to validate properties. - - This instance will be passed to all - calls executed by the current viewmodel, and its property will be updated every time - before the call is made to set the name of the property being validated. The property name will not be reset after that, so the - value of will always indicate the name of the last property that was validated, if any. - - - Thrown if is . - - - - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with - the new value, then raises the event. - - The type of the property that changed. - The field storing the property's value. - The property's value after the change occurred. - If , will also be validated. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - This method is just like , just with the addition - of the parameter. If that is set to , the new value will be - validated and will be raised if needed. Following the behavior of the base method, - the and events - are not raised if the current and new value for the target property are the same. - - Thrown if is . - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with - the new value, then raises the event. - See additional notes about this overload in . - - The type of the property that changed. - The field storing the property's value. - The property's value after the change occurred. - The instance to use to compare the input values. - If , will also be validated. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if or are . - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with - the new value, then raises the event. Similarly to - the method, this overload should only be - used when can't be used directly. - - The type of the property that changed. - The current property value. - The property's value after the change occurred. - A callback to invoke to update the property value. - If , will also be validated. - (optional) The name of the property that changed. - if the property was changed, otherwise. - - This method is just like , just with the addition - of the parameter. As such, following the behavior of the base method, - the and events - are not raised if the current and new value for the target property are the same. - - Thrown if or are . - - - - Compares the current and new values for a given property. If the value has changed, - raises the event, updates the property with - the new value, then raises the event. - See additional notes about this overload in . - - The type of the property that changed. - The current property value. - The property's value after the change occurred. - The instance to use to compare the input values. - A callback to invoke to update the property value. - If , will also be validated. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if , or are . - - - - Compares the current and new values for a given nested property. If the value has changed, - raises the event, updates the property and then raises the - event. The behavior mirrors that of - , with the difference being that this - method is used to relay properties from a wrapped model in the current instance. For more info, see the docs for - . - - The type of model whose property (or field) to set. - The type of property (or field) to set. - The current property value. - The property's value after the change occurred. - The model - The callback to invoke to set the target property value, if a change has occurred. - If , will also be validated. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if , or are . - - - - Compares the current and new values for a given nested property. If the value has changed, - raises the event, updates the property and then raises the - event. The behavior mirrors that of - , - with the difference being that this method is used to relay properties from a wrapped model in the - current instance. For more info, see the docs for - . - - The type of model whose property (or field) to set. - The type of property (or field) to set. - The current property value. - The property's value after the change occurred. - The instance to use to compare the input values. - The model - The callback to invoke to set the target property value, if a change has occurred. - If , will also be validated. - (optional) The name of the property that changed. - if the property was changed, otherwise. - Thrown if , , or are . - - - - Tries to validate a new value for a specified property. If the validation is successful, - is called, otherwise no state change is performed. - - The type of the property that changed. - The field storing the property's value. - The property's value after the change occurred. - The resulting validation errors, if any. - (optional) The name of the property that changed. - Whether the validation was successful and the property value changed as well. - Thrown if is . - - - - Tries to validate a new value for a specified property. If the validation is successful, - is called, otherwise no state change is performed. - - The type of the property that changed. - The field storing the property's value. - The property's value after the change occurred. - The instance to use to compare the input values. - The resulting validation errors, if any. - (optional) The name of the property that changed. - Whether the validation was successful and the property value changed as well. - Thrown if or are . - - - - Tries to validate a new value for a specified property. If the validation is successful, - is called, otherwise no state change is performed. - - The type of the property that changed. - The current property value. - The property's value after the change occurred. - A callback to invoke to update the property value. - The resulting validation errors, if any. - (optional) The name of the property that changed. - Whether the validation was successful and the property value changed as well. - Thrown if or are . - - - - Tries to validate a new value for a specified property. If the validation is successful, - is called, otherwise no state change is performed. - - The type of the property that changed. - The current property value. - The property's value after the change occurred. - The instance to use to compare the input values. - A callback to invoke to update the property value. - The resulting validation errors, if any. - (optional) The name of the property that changed. - Whether the validation was successful and the property value changed as well. - Thrown if , or are . - - - - Tries to validate a new value for a specified property. If the validation is successful, - is called, otherwise no state change is performed. - - The type of model whose property (or field) to set. - The type of property (or field) to set. - The current property value. - The property's value after the change occurred. - The model - The callback to invoke to set the target property value, if a change has occurred. - The resulting validation errors, if any. - (optional) The name of the property that changed. - Whether the validation was successful and the property value changed as well. - Thrown if , or are . - - - - Tries to validate a new value for a specified property. If the validation is successful, - is called, otherwise no state change is performed. - - The type of model whose property (or field) to set. - The type of property (or field) to set. - The current property value. - The property's value after the change occurred. - The instance to use to compare the input values. - The model - The callback to invoke to set the target property value, if a change has occurred. - The resulting validation errors, if any. - (optional) The name of the property that changed. - Whether the validation was successful and the property value changed as well. - Thrown if , , or are . - - - - Clears the validation errors for a specified property or for the entire entity. - - - The name of the property to clear validation errors for. - If a or empty name is used, all entity-level errors will be cleared. - - - - - - - - - - - Validates all the properties in the current instance and updates all the tracked errors. - If any changes are detected, the event will be raised. - - - Only public instance properties (excluding custom indexers) that have at least one - applied to them will be validated. All other - members in the current instance will be ignored. None of the processed properties - will be modified - they will only be used to retrieve their values and validate them. - - - - - Validates a property with a specified name and a given input value. - If any changes are detected, the event will be raised. - - The value to test for the specified property. - The name of the property to validate. - Thrown when is . - - - - Tries to validate a property with a specified name and a given input value, and returns - the computed errors, if any. If the property is valid, it is assumed that its value is - about to be set in the current object. Otherwise, no observable local state is modified. - - The value to test for the specified property. - The name of the property to validate. - The resulting validation errors, if any. - - - - Clears all the current errors for the entire entity. - - - - - Clears all the current errors for a target property. - - The name of the property to clear errors for. - - - - Gets the display name for a given property. It could be a custom name or just the property name. - - The target property name being validated. - The display name for the property. - - - - An internal helper to support the source generator APIs related to . - This type is not intended to be used directly by user code. - - - - - Invokes externally on a target instance. - - The target instance. - The value to test for the specified property. - The name of the property to validate. - - - - An internal helper used to support and generated code from its template. - This type is not intended to be used directly by user code. - - - - - Gets an awaitable object that skips end validation. - - The input to get the awaitable for. - A object wrapping . - - - - A custom task awaitable object that skips end validation. - - - - - The wrapped instance to create an awaiter for. - - - - - Creates a new instance with the specified parameters. - - The wrapped instance to create an awaiter for. - - - - Gets an instance for the current underlying task. - - An instance for the current underlying task. - - - - An awaiter object for . - - - - - The underlying instance. - - - - - Creates a new instance with the specified parameters. - - The wrapped instance to create an awaiter for. - - - - Gets whether the operation has completed or not. - - This property is intended for compiler user rather than use directly in code. - - - - Ends the await operation. - - This method is intended for compiler user rather than use directly in code. - - - - - - - - - - A type that facilitates the use of the type. - The provides the ability to configure services in a singleton, thread-safe - service provider instance, which can then be used to resolve service instances. - The first step to use this feature is to declare some services, for instance: - - public interface ILogger - { - void Log(string text); - } - - - public class ConsoleLogger : ILogger - { - void Log(string text) => Console.WriteLine(text); - } - - Then the services configuration should then be done at startup, by calling the - method and passing an instance with the services to use. That instance can - be from any library offering dependency injection functionality, such as Microsoft.Extensions.DependencyInjection. - For instance, using that library, can be used as follows in this example: - - Ioc.Default.ConfigureServices( - new ServiceCollection() - .AddSingleton<ILogger, Logger>() - .BuildServiceProvider()); - - Finally, you can use the instance (which implements ) - to retrieve the service instances from anywhere in your application, by doing as follows: - - Ioc.Default.GetService<ILogger>().Log("Hello world!"); - - - - - - Gets the default instance. - - - - - The instance to use, if initialized. - - - - - - - - Tries to resolve an instance of a specified service type. - - The type of service to resolve. - An instance of the specified service, or . - Thrown if the current instance has not been initialized. - - - - Resolves an instance of a specified service type. - - The type of service to resolve. - An instance of the specified service, or . - - Thrown if the current instance has not been initialized, or if the - requested service type was not registered in the service provider currently in use. - - - - - Initializes the shared instance. - - The input instance to use. - Thrown if is . - - - - Throws an when the property is used before initialization. - - - - - Throws an when the property is missing a type registration. - - - - - Throws an when a configuration is attempted more than once. - - - - - A command that mirrors the functionality of , with the addition of - accepting a returning a as the execute - action, and providing an property that notifies changes when - is invoked and when the returned completes. - - - - - The cached for . - - - - - The cached for . - - - - - The cached for . - - - - - The cached for . - - - - - The to invoke when is used. - - - - - The cancelable to invoke when is used. - - Only one between this and is not . - - - - The optional action to invoke when is used. - - - - - The options being set for the current command. - - - - - The instance to use to cancel . - - This is only used when is not . - - - - - - - - - - Initializes a new instance of the class. - - The execution logic. - Thrown if is . - - - - Initializes a new instance of the class. - - The execution logic. - The options to use to configure the async command. - Thrown if is . - - - - Initializes a new instance of the class. - - The cancelable execution logic. - Thrown if is . - - - - Initializes a new instance of the class. - - The cancelable execution logic. - The options to use to configure the async command. - Thrown if is . - - - - Initializes a new instance of the class. - - The execution logic. - The execution status logic. - Thrown if or are . - - - - Initializes a new instance of the class. - - The execution logic. - The execution status logic. - The options to use to configure the async command. - Thrown if or are . - - - - Initializes a new instance of the class. - - The cancelable execution logic. - The execution status logic. - Thrown if or are . - - - - Initializes a new instance of the class. - - The cancelable execution logic. - The execution status logic. - The options to use to configure the async command. - Thrown if or are . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Awaits an input and throws an exception on the calling context, if the task fails. - - The input instance to await. - - - - Options to customize the behavior of and instances. - - - - - No option is specified. The and types will use their default behavior: - - Concurrent execution is disallowed: a command is disabled if there is a pending asynchronous execution running. - - - Exceptions are thrown on the calling context: calling will await the - returned for the operation, and propagate the exception on the calling context. - - This behavior is consistent with synchronous commands, where exceptions in behave the same. - - - - - - - Concurrent executions are allowed. This option makes it so that the same command can be invoked concurrently multiple times. - - Note that additional considerations should be taken into account in this case: - - If the command supports cancellation, previous invocations will automatically be canceled if a new one is started. - The property will always represent the operation that was started last. - - - - - - - Exceptions are not thrown on the calling context, and are propagated to instead. - - This affects how calls to behave. When this option is used, if an operation fails, that exception will not - be rethrown on the calling context (as it is not awaited there). Instead, it will flow to . - - - This option enables more advanced scenarios, where the property can be used to inspect the state of an operation - that was queued. That is, even if the operation failed or was canceled, the details of that can be retrieved at a later time by accessing this property. - - - - - - A generic command that provides a more specific version of . - - The type of parameter being passed as input to the callbacks. - - - - The to invoke when is used. - - - - - The cancelable to invoke when is used. - - - - - The optional action to invoke when is used. - - - - - The options being set for the current command. - - - - - The instance to use to cancel . - - - - - - - - - - - Initializes a new instance of the class. - - The execution logic. - See notes in . - Thrown if is . - - - - Initializes a new instance of the class. - - The execution logic. - The options to use to configure the async command. - See notes in . - Thrown if is . - - - - Initializes a new instance of the class. - - The cancelable execution logic. - See notes in . - Thrown if is . - - - - Initializes a new instance of the class. - - The cancelable execution logic. - The options to use to configure the async command. - See notes in . - Thrown if is . - - - - Initializes a new instance of the class. - - The execution logic. - The execution status logic. - See notes in . - Thrown if or are . - - - - Initializes a new instance of the class. - - The execution logic. - The execution status logic. - The options to use to configure the async command. - See notes in . - Thrown if or are . - - - - Initializes a new instance of the class. - - The cancelable execution logic. - The execution status logic. - See notes in . - Thrown if or are . - - - - Initializes a new instance of the class. - - The cancelable execution logic. - The execution status logic. - The options to use to configure the async command. - See notes in . - Thrown if or are . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - An attribute that can be used to automatically generate properties from declared methods. When this attribute - is used to decorate a method, a generator will create a command property with the corresponding interface - depending on the signature of the method. If an invalid method signature is used, the generator will report an error. - - In order to use this attribute, the containing type doesn't need to implement any interfaces. The generated properties will be lazily - assigned but their value will never change, so there is no need to support property change notifications or other additional functionality. - - - This attribute can be used as follows: - - partial class MyViewModel - { - [RelayCommand] - private void GreetUser(User? user) - { - Console.WriteLine($"Hello {user.Name}!"); - } - } - - And with this, code analogous to this will be generated: - - partial class MyViewModel - { - private RelayCommand? greetUserCommand; - - public IRelayCommand GreetUserCommand => greetUserCommand ??= new RelayCommand(GreetUser); - } - - - - The following signatures are supported for annotated methods: - - void Method(); - - Will generate an property (using a instance). - - void Method(T?); - - Will generate an property (using a instance). - - Task Method(); - Task Method(CancellationToken); - Task<T> Method(); - Task<T> Method(CancellationToken); - - Will both generate an property (using an instance). - - Task Method(T?); - Task Method(T?, CancellationToken); - Task<T> Method(T?); - Task<T> Method(T?, CancellationToken); - - Will both generate an property (using an instance). - - - - - - Gets or sets the name of the property or method that will be invoked to check whether the - generated command can be executed at any given time. The referenced member needs to return - a value, and has to have a signature compatible with the target command. - - - - - Gets or sets a value indicating whether or not to allow concurrent executions for an asynchronous command. - - When set for an attribute used on a method that would result in an or an - property to be generated, this will modify the behavior of these commands - when an execution is invoked while a previous one is still running. It is the same as creating an instance of - these command types with a constructor such as - and using the value. - - - Using this property is not valid if the target command doesn't map to an asynchronous command. - - - - Gets or sets a value indicating whether or not to exceptions should be propagated to . - - When set for an attribute used on a method that would result in an or an - property to be generated, this will modify the behavior of these commands - in case an exception is thrown by the underlying operation. It is the same as creating an instance of - these command types with a constructor such as - and using the value. - - - Using this property is not valid if the target command doesn't map to an asynchronous command. - - - - Gets or sets a value indicating whether a cancel command should also be generated for an asynchronous command. - - When set to , this additional code will be generated: - - partial class MyViewModel - { - private ICommand? loginUserCancelCommand; - - public ICommand LoginUserCancelCommand => loginUserCancelCommand ??= LoginUserCommand.CreateCancelCommand(); - } - - Where LoginUserCommand is an defined in the class (or generated by this attribute as well). - - - Using this property is not valid if the target command doesn't map to a cancellable asynchronous command. - - - - Extensions for the type. - - - - - Creates an instance that can be used to cancel execution on the input command. - The returned command will also notify when it can be executed based on the state of the wrapped command. - - The input instance to create a cancellation command for. - An instance that can be used to monitor and signal cancellation for . - The returned instance is not guaranteed to be unique across multiple invocations with the same arguments. - Thrown if is . - - - - An interface expanding to support asynchronous operations. - - - - - Gets the last scheduled , if available. - This property notifies a change when the completes. - - - - - Gets a value indicating whether a running operation for this command can currently be canceled. - - - The exact sequence of events that types implementing this interface should raise is as follows: - - - The command is initially not running: , - and are . - - - The command starts running: and switch to - . is set to . - - - If the operation is canceled: switches to - and switches to . - - - The operation completes: and switch - to . The state of is undefined. - - - This only applies if the underlying logic for the command actually supports cancelation. If that is - not the case, then and will always remain - regardless of the current state of the command. - - - - - Gets a value indicating whether a cancelation request has been issued for the current operation. - - - - - Gets a value indicating whether the command currently has a pending operation being executed. - - - - - Provides a more specific version of , - also returning the representing the async operation being executed. - - The input parameter. - The representing the async operation being executed. - Thrown if is incompatible with the underlying command implementation. - - - - Communicates a request for cancelation. - - - If the underlying command is not running, or if it does not support cancelation, this method will perform no action. - Note that even with a successful cancelation, the completion of the current operation might not be immediate. - - - - - A generic interface representing a more specific version of . - - The type used as argument for the interface methods. - This interface is needed to solve the diamond problem with base classes. - - - - Provides a strongly-typed variant of . - - The input parameter. - The representing the async operation being executed. - - - - An interface expanding with the ability to raise - the event externally. - - - - - Notifies that the property has changed. - - - - - A generic interface representing a more specific version of . - - The type used as argument for the interface methods. - - - - Provides a strongly-typed variant of . - - The input parameter. - Whether or not the current command can be executed. - Use this overload to avoid boxing, if is a value type. - - - - Provides a strongly-typed variant of . - - The input parameter. - Use this overload to avoid boxing, if is a value type. - - - - A implementation wrapping to support cancellation. - - - - - The wrapped instance. - - - - - Creates a new instance. - - The instance to wrap. - - - - - - - - - - - - - - - - A reusable instance that is always disabled. - - - - - - - - Gets a shared, reusable instance. - - - This instance can safely be used across multiple objects without having - to worry about this static keeping others alive, as the event uses a - custom accessor that just discards items (as the event is known to never - be raised). As such, this instance will never act as root for other objects. - - - - - - - - - - - An interface for commands that know whether they support cancellation or not. - - - - - Gets whether or not the current command supports cancellation. - - - - - A command whose sole purpose is to relay its functionality to other - objects by invoking delegates. The default return value for the - method is . This type does not allow you to accept command parameters - in the and callback methods. - - - - - The to invoke when is used. - - - - - The optional action to invoke when is used. - - - - - - - - Initializes a new instance of the class that can always execute. - - The execution logic. - Thrown if is . - - - - Initializes a new instance of the class. - - The execution logic. - The execution status logic. - Thrown if or are . - - - - - - - - - - - - - A generic command whose sole purpose is to relay its functionality to other - objects by invoking delegates. The default return value for the CanExecute - method is . This class allows you to accept command parameters - in the and callback methods. - - The type of parameter being passed as input to the callbacks. - - - - The to invoke when is used. - - - - - The optional action to invoke when is used. - - - - - - - - Initializes a new instance of the class that can always execute. - - The execution logic. - - Due to the fact that the interface exposes methods that accept a - nullable parameter, it is recommended that if is a reference type, - you should always declare it as nullable, and to always perform checks within . - - Thrown if is . - - - - Initializes a new instance of the class. - - The execution logic. - The execution status logic. - See notes in . - Thrown if or are . - - - - - - - - - - - - - - - - - - - Tries to get a command argument of compatible type from an input . - - The input parameter. - The resulting value, if any. - Whether or not a compatible command argument could be retrieved. - - - - Throws an if an invalid command argument is used. - - The input parameter. - Thrown with an error message to give info on the invalid parameter. - - - - An interface for a type providing the ability to exchange messages between different objects. - This can be useful to decouple different modules of an application without having to keep strong - references to types being referenced. It is also possible to send messages to specific channels, uniquely - identified by a token, and to have different messengers in different sections of an applications. - In order to use the functionalities, first define a message type, like so: - - public sealed class LoginCompletedMessage { } - - Then, register your a recipient for this message: - - Messenger.Default.Register<MyRecipientType, LoginCompletedMessage>(this, (r, m) => - { - // Handle the message here... - }); - - The message handler here is a lambda expression taking two parameters: the recipient and the message. - This is done to avoid the allocations for the closures that would've been generated if the expression - had captured the current instance. The recipient type parameter is used so that the recipient can be - directly accessed within the handler without the need to manually perform type casts. This allows the - code to be less verbose and more reliable, as all the checks are done just at build time. If the handler - is defined within the same type as the recipient, it is also possible to directly access private members. - This allows the message handler to be a static method, which enables the C# compiler to perform a number - of additional memory optimizations (such as caching the delegate, avoiding unnecessary memory allocations). - Finally, send a message when needed, like so: - - Messenger.Default.Send<LoginCompletedMessage>(); - - Additionally, the method group syntax can also be used to specify the message handler - to invoke when receiving a message, if a method with the right signature is available - in the current scope. This is helpful to keep the registration and handling logic separate. - Following up from the previous example, consider a class having this method: - - private static void Receive(MyRecipientType recipient, LoginCompletedMessage message) - { - // Handle the message there - } - - The registration can then be performed in a single line like so: - - Messenger.Default.Register(this, Receive); - - The C# compiler will automatically convert that expression to a instance - compatible with . - This will also work if multiple overloads of that method are available, each handling a different - message type: the C# compiler will automatically pick the right one for the current message type. - It is also possible to register message handlers explicitly using the interface. - To do so, the recipient just needs to implement the interface and then call the - extension, which will automatically register - all the handlers that are declared by the recipient type. Registration for individual handlers is supported as well. - - - - - Checks whether or not a given recipient has already been registered for a message. - - The type of message to check for the given recipient. - The type of token to check the channel for. - The target recipient to check the registration for. - The token used to identify the target channel to check. - Whether or not has already been registered for the specified message. - Thrown if or are . - - - - Registers a recipient for a given type of message. - - The type of recipient for the message. - The type of message to receive. - The type of token to use to pick the messages to receive. - The recipient that will receive the messages. - A token used to determine the receiving channel to use. - The to invoke when a message is received. - Thrown if , or are . - Thrown when trying to register the same message twice. - - - - Unregisters a recipient from all registered messages. - - The recipient to unregister. - - This method will unregister the target recipient across all channels. - Use this method as an easy way to lose all references to a target recipient. - If the recipient has no registered handler, this method does nothing. - - Thrown if is . - - - - Unregisters a recipient from all messages on a specific channel. - - The type of token to identify what channel to unregister from. - The recipient to unregister. - The token to use to identify which handlers to unregister. - If the recipient has no registered handler, this method does nothing. - Thrown if or are . - - - - Unregisters a recipient from messages of a given type. - - The type of message to stop receiving. - The type of token to identify what channel to unregister from. - The recipient to unregister. - The token to use to identify which handlers to unregister. - If the recipient has no registered handler, this method does nothing. - Thrown if or are . - - - - Sends a message of the specified type to all registered recipients. - - The type of message to send. - The type of token to identify what channel to use to send the message. - The message to send. - The token indicating what channel to use. - The message that was sent (ie. ). - Thrown if or are . - - - - Performs a cleanup on the current messenger. - Invoking this method does not unregister any of the currently registered - recipient, and it can be used to perform cleanup operations such as - trimming the internal data structures of a messenger implementation. - - - - - Resets the instance and unregisters all the existing recipients. - - - - - Extensions for the type. - - - - - - A class that acts as a container to load the instance linked to - the method. - This class is needed to avoid forcing the initialization code in the static constructor to run as soon as - the type is referenced, even if that is done just to use methods - that do not actually require this instance to be available. - We're effectively using this type to leverage the lazy loading of static constructors done by the runtime. - - - - - The instance associated with . - - - - - A non-generic version of . - - - - - The instance used to track the preloaded registration action for each recipient. - - - - - A class that acts as a static container to associate a instance to each - type in use. This is done because we can only use a single type as key, but we need to track - associations of each recipient type also across different communication channels, each identified by a token. - Since the token is actually a compile-time parameter, we can use a wrapping class to let the runtime handle a different - instance for each generic type instantiation. This lets us only worry about the recipient type being inspected. - - The token indicating what channel to use. - - - - The instance used to track the preloaded registration action for each recipient. - - - - - Checks whether or not a given recipient has already been registered for a message. - - The type of message to check for the given recipient. - The instance to use to check the registration. - The target recipient to check the registration for. - Whether or not has already been registered for the specified message. - This method will use the default channel to check for the requested registration. - Thrown if or are . - - - - Registers all declared message handlers for a given recipient, using the default channel. - - The instance to use to register the recipient. - The recipient that will receive the messages. - See notes for for more info. - Thrown if or are . - - - - Registers all declared message handlers for a given recipient. - - The type of token to identify what channel to use to receive messages. - The instance to use to register the recipient. - The recipient that will receive the messages. - The token indicating what channel to use. - - This method will register all messages corresponding to the interfaces - being implemented by . If none are present, this method will do nothing. - Note that unlike all other extensions, this method will use reflection to find the handlers to register. - Once the registration is complete though, the performance will be exactly the same as with handlers - registered directly through any of the other generic extensions for the interface. - - Thrown if , or are . - - - - Registers a recipient for a given type of message. - - The type of message to receive. - The instance to use to register the recipient. - The recipient that will receive the messages. - Thrown when trying to register the same message twice. - This method will use the default channel to perform the requested registration. - Thrown if or are . - - - - Registers a recipient for a given type of message. - - The type of message to receive. - The type of token to identify what channel to use to receive messages. - The instance to use to register the recipient. - The recipient that will receive the messages. - The token indicating what channel to use. - Thrown when trying to register the same message twice. - This method will use the default channel to perform the requested registration. - Thrown if , or are . - - - - Registers a recipient for a given type of message. - - The type of message to receive. - The instance to use to register the recipient. - The recipient that will receive the messages. - The to invoke when a message is received. - Thrown when trying to register the same message twice. - This method will use the default channel to perform the requested registration. - Thrown if , or are . - - - - Registers a recipient for a given type of message. - - The type of recipient for the message. - The type of message to receive. - The instance to use to register the recipient. - The recipient that will receive the messages. - The to invoke when a message is received. - Thrown when trying to register the same message twice. - This method will use the default channel to perform the requested registration. - Thrown if , or are . - - - - Registers a recipient for a given type of message. - - The type of message to receive. - The type of token to use to pick the messages to receive. - The instance to use to register the recipient. - The recipient that will receive the messages. - A token used to determine the receiving channel to use. - The to invoke when a message is received. - Thrown when trying to register the same message twice. - Thrown if , or are . - - - - Unregisters a recipient from messages of a given type. - - The type of message to stop receiving. - The instance to use to unregister the recipient. - The recipient to unregister. - - This method will unregister the target recipient only from the default channel. - If the recipient has no registered handler, this method does nothing. - - Thrown if or are . - - - - Sends a message of the specified type to all registered recipients. - - The type of message to send. - The instance to use to send the message. - The message that has been sent. - - This method is a shorthand for when the - message type exposes a parameterless constructor: it will automatically create - a new instance and send that to its recipients. - - Thrown if is . - - - - Sends a message of the specified type to all registered recipients. - - The type of message to send. - The instance to use to send the message. - The message to send. - The message that was sent (ie. ). - Thrown if or are . - - - - Sends a message of the specified type to all registered recipients. - - The type of message to send. - The type of token to identify what channel to use to send the message. - The instance to use to send the message. - The token indicating what channel to use. - The message that has been sen. - - This method will automatically create a new instance - just like , and then send it to the right recipients. - - Thrown if or are . - - - - Creates an instance that can be used to be notified whenever a message of a given type is broadcast by a messenger. - - The type of message to use to receive notification for through the resulting instance. - The instance to use to register the recipient. - An instance to receive notifications for messages being broadcast. - Thrown if is . - - - - Creates an instance that can be used to be notified whenever a message of a given type is broadcast by a messenger. - - The type of message to use to receive notification for through the resulting instance. - The type of token to identify what channel to use to receive messages. - The instance to use to register the recipient. - A token used to determine the receiving channel to use. - An instance to receive notifications for messages being broadcast. - Thrown if or are . - - - - An implementations for a given message type. - - The type of messages to listen to. - - - - The instance to use to register the recipient. - - - - - Creates a new instance with the given parameters. - - The instance to use to register the recipient. - - - - - - - An implementation for . - - - - - The instance to use to register the recipient. - - - - - The target instance currently in use. - - - - - Creates a new instance with the specified parameters. - - The instance to use to register the recipient. - The instance to use to create the recipient for. - - - - - - - - - - An implementations for a given pair of message and token types. - - The type of messages to listen to. - The type of token to identify what channel to use to receive messages. - - - - The instance to use to register the recipient. - - - - - The token used to determine the receiving channel to use. - - - - - Creates a new instance with the given parameters. - - The instance to use to register the recipient. - A token used to determine the receiving channel to use. - - - - - - - An implementation for . - - - - - The instance to use to register the recipient. - - - - - The target instance currently in use. - - - - - The token used to determine the receiving channel to use. - - - - - Creates a new instance with the specified parameters. - - The instance to use to register the recipient. - The instance to use to create the recipient for. - A token used to determine the receiving channel to use. - - - - - - - - - - A simple buffer writer implementation using pooled arrays. - - The type of items to store in the list. - - This type is a to avoid the object allocation and to - enable the pattern-based support. We aren't worried with consumers not - using this type correctly since it's private and only accessible within the parent type. - - - - - The default buffer size to use to expand empty arrays. - - - - - The underlying array. - - - - - The span mapping to . - - All writes are done through this to avoid covariance checks. - - - - The starting offset within . - - - - - Creates a new instance of the struct. - - A new instance. - - - - Gets a with the current items. - - - - - Adds a new item to the current collection. - - The item to add. - - - - Resets the underlying array and the stored items. - - - - - Resizes when there is no space left for new items, then adds one - - The item to add. - - - - - - - A dispatcher type that invokes a given callback. - - - This type is used to avoid type aliasing with when the generic - arguments are not known. Additionally, this is an abstract class and not an interface so that when - is called, virtual dispatch will be used instead of interface - stub dispatch, which is much slower and with more indirections. - - - - - Invokes the current callback on a target recipient, with a specified message. - - The target recipient for the message. - The message being broadcast. - - - - A generic version of . - - The type of recipient for the message. - The type of message to receive. - - - - The underlying callback to invoke. - - - - - Initializes a new instance of the class. - - The input instance. - - - - - - - A simple type representing an immutable pair of types. - - - This type replaces a simple as it's faster in its - and methods, and because - unlike a value tuple it exposes its fields as immutable. Additionally, the - and fields provide additional clarity reading - the code compared to and . - - - - - The type of registered message. - - - - - The type of registration token. - - - - - Initializes a new instance of the struct. - - The type of registered message. - The type of registration token. - - - - - - - - - - - - - An empty type representing a generic token with no specific value. - - - - - - - - - - - - - - An interface for a recipient that declares a registration for a specific message type. - - The type of message to receive. - - - - Receives a given message instance. - - The message being received. - - - - A used to represent actions to invoke when a message is received. - The recipient is given as an input argument to allow message registrations to avoid creating - closures: if an instance method on a recipient needs to be invoked it is possible to just - cast the recipient to the right type and then access the local method from that instance. - - The type of recipient for the message. - The type of message to receive. - The recipient that is receiving the message. - The message being received. - - - - A for request messages that can receive multiple replies, which can either be used directly or through derived classes. - - The type of request to make. - - - - The collection of received replies. We accept both instance, representing already running - operations that can be executed in parallel, or instances, which can be used so that multiple - asynchronous operations are only started sequentially from and do not overlap in time. - - - - - The instance used to link the token passed to - and the one passed to all subscribers to the message. - - - - - Gets the instance that will be linked to the - one used to asynchronously enumerate the received responses. This can be used to cancel asynchronous - replies that are still being processed, if no new items are needed from this request message. - Consider the following example, where we define a message to retrieve the currently opened documents: - - public class OpenDocumentsRequestMessage : AsyncCollectionRequestMessage<XmlDocument> { } - - We can then request and enumerate the results like so: - - await foreach (var document in Messenger.Default.Send<OpenDocumentsRequestMessage>()) - { - // Process each document here... - } - - If we also want to control the cancellation of the token passed to each subscriber to the message, - we can do so by passing a token we control to the returned message before starting the enumeration - (). - The previous snippet with this additional change looks as follows: - - await foreach (var document in Messenger.Default.Send<OpenDocumentsRequestMessage>().WithCancellation(cts.Token)) - { - // Process each document here... - } - - When no more new items are needed (or for any other reason depending on the situation), the token - passed to the enumerator can be canceled (by calling ), - and that will also notify the remaining tasks in the request message. The token exposed by the message - itself will automatically be linked and canceled with the one passed to the enumerator. - - - - - Replies to the current request message. - - The response to use to reply to the request message. - - - - Replies to the current request message. - - The response to use to reply to the request message. - Thrown if is . - - - - Replies to the current request message. - - The response to use to reply to the request message. - Thrown if is . - - - - Gets the collection of received response items. - - A value to stop the operation. - The collection of received response items. - - - - - - - A for async request messages, which can either be used directly or through derived classes. - - The type of request to make. - - - - Gets the message response. - - Thrown when is . - - - - Gets a value indicating whether a response has already been assigned to this instance. - - - - - Replies to the current request message. - - The response to use to reply to the request message. - Thrown if has already been set. - - - - Replies to the current request message. - - The response to use to reply to the request message. - Thrown if is . - Thrown if has already been set. - - - - - - - Throws an when a response is not available. - - - - - Throws an when or are called twice. - - - - - A for request messages that can receive multiple replies, which can either be used directly or through derived classes. - - The type of request to make. - - - - Gets the message responses. - - - - - Replies to the current request message. - - The response to use to reply to the request message. - - - - - - - - - - A message used to broadcast property changes in observable objects. - - The type of the property to broadcast the change for. - - - - Initializes a new instance of the class. - - The original sender of the broadcast message. - The name of the property that changed. - The value that the property had before the change. - The value that the property has after the change. - Thrown if is . - - - - Gets the original sender of the broadcast message. - - - - - Gets the name of the property that changed. - - - - - Gets the value that the property had before the change. - - - - - Gets the value that the property has after the change. - - - - - A for request messages, which can either be used directly or through derived classes. - - The type of request to make. - - - - Gets the message response. - - Thrown when is . - - - - Gets a value indicating whether a response has already been assigned to this instance. - - - - - Replies to the current request message. - - The response to use to reply to the request message. - Thrown if has already been set. - - - - Implicitly gets the response from a given instance. - - The input instance. - Thrown if is . - Thrown when is . - - - - Throws an when a response is not available. - - - - - Throws an when is called twice. - - - - - A base message that signals whenever a specific value has changed. - - The type of value that has changed. - - - - Initializes a new instance of the class. - - The value that has changed. - - - - Gets the value that has changed. - - - - - A class providing a reference implementation for the interface. - - - This implementation uses strong references to track the registered - recipients, so it is necessary to manually unregister them when they're no longer needed. - - - - - The collection of currently registered recipients, with a link to their linked message receivers. - - - This collection is used to allow reflection-free access to all the existing - registered recipients from and other methods in this type, - so that all the existing handlers can be removed without having to dynamically create - the generic types for the containers of the various dictionaries mapping the handlers. - - - - - The and instance for types combination. - - - The values are just of type as we don't know the type parameters in advance. - Each method relies on to get the type-safe instance of the - or class for each pair of generic arguments in use. - - - - - Gets the default instance. - - - - - - - - - - - - - - Registers a recipient for a given type of message. - - The type of message to receive. - The type of token to use to pick the messages to receive. - The recipient that will receive the messages. - A token used to determine the receiving channel to use. - The input instance to register, or null. - Thrown when trying to register the same message twice. - - - - - - - - - - - - - - - - - - - - - - Tries to get the instance of currently - registered recipients for the input type. - - The type of message to send. - The resulting instance, if found. - Whether or not the required instance was found. - - - - Tries to get the instance of currently registered recipients - for the combination of types and . - - The type of message to send. - The type of token to identify what channel to use to send the message. - The resulting instance, if found. - Whether or not the required instance was found. - - - - Gets the instance of currently - registered recipients for the input type. - - The type of message to send. - A instance with the requested type arguments. - - - - Gets the instance of currently registered recipients - for the combination of types and . - - The type of message to send. - The type of token to identify what channel to use to send the message. - A instance with the requested type arguments. - - - - A mapping type representing a link to recipients and their view of handlers per communication channel. - - - This type is a specialization of for tokens. - - - - - Initializes a new instance of the class. - - The message type being used. - - - - Creates a new instance of the class. - - The type of message to receive. - A new instance. - - - - - - - A mapping type representing a link to recipients and their view of handlers per communication channel. - - The type of token to use to pick the messages to receive. - - This type is defined for simplicity and as a workaround for the lack of support for using type aliases - over open generic types in C# (using type aliases can only be used for concrete, closed types). - - - - - Initializes a new instance of the class. - - The message type being used. - - - - Creates a new instance of the class. - - The type of message to receive. - A new instance. - - - - - - - An interface for the and types which allows to retrieve - the type arguments from a given generic instance without having any prior knowledge about those arguments. - - - - - Gets the instance representing the current type arguments. - - - - - A simple type representing a recipient. - - - This type is used to enable fast indexing in each mapping dictionary, - since it acts as an external override for the and - methods for arbitrary objects, removing both - the virtual call and preventing instances overriding those methods in this context. - Using this type guarantees that all the equality operations are always only done - based on reference equality for each registered recipient, regardless of its type. - - - - - The registered recipient. - - - - - Initializes a new instance of the struct. - - The target recipient instance. - - - - - - - - - - - - - Throws an when trying to add a duplicate handler. - - - - - A class providing a reference implementation for the interface. - - - - This implementation uses weak references to track the registered - recipients, so it is not necessary to manually unregister them when they're no longer needed. - - - The type will automatically perform internal trimming when - full GC collections are invoked, so calling manually is not necessary to - ensure that on average the internal data structures are as trimmed and compact as possible. - - - - - - The map of currently registered recipients for all message types. - - - - - Initializes a new instance of the class. - - - - - Gets the default instance. - - - - - - - - - - - Registers a recipient for a given type of message. - - The type of message to receive. - The type of token to use to pick the messages to receive. - The recipient that will receive the messages. - A token used to determine the receiving channel to use. - Thrown when trying to register the same message twice. - - This method is a variation of - that is specialized for recipients implementing . See more comments at the top of this type, as well as - within and in the types. - - - - - Registers a recipient for a given type of message. - - The type of message to receive. - The type of token to use to pick the messages to receive. - The recipient that will receive the messages. - A token used to determine the receiving channel to use. - The input instance to register, or null. - Thrown when trying to register the same message twice. - - - - - - - - - - - - - - - - Implements the broadcasting logic for . - - - - - - - This method is not a local function to avoid triggering multiple compilations due to TToken - potentially being a value type, which results in specialized code due to reified generics. This is - necessary to work around a Roslyn limitation that causes unnecessary type parameters in local - functions not to be discarded in the synthesized methods. Additionally, keeping this loop outside - of the EH block (the block) can help result in slightly better codegen. - - - - - - - - - - - Executes a cleanup without locking the current instance. This method has to be - invoked when a lock on has already been acquired. - - - - - Executes a cleanup without locking the current instance. This method has to be - invoked when a lock on has already been acquired. - - - - - Throws an when trying to add a duplicate handler. - - - - - A container for all shared configuration switches for the MVVM Toolkit. - - - - This type uses a very specific setup for configuration switches to ensure ILLink can work the best. - This mirrors the architecture of feature switches in the runtime as well, and it's needed so that - no static constructor is generated for the type. - - - For more info, see . - - - - - - The configuration property name for . - - - - - The backing field for . - - - - - Gets a value indicating whether or not support for should be enabled (defaults to ). - - - - - Gets a configuration value for a specified property. - - The property name to retrieve the value for. - The cached result for the target configuration value. - The default value for the feature switch, if not set. - The value of the specified configuration setting. - - - - Internal polyfill for . - - - - - Throws an if is . - - The reference type argument to validate as non-. - The name of the parameter with which corresponds. - - - - A specialized version for generic values. - - The type of values to check. - - This type is needed because if there had been a generic overload with a generic parameter, all calls - would have just been bound by that by the compiler instead of the overload. - - - - - Throws an if is . - - The reference type argument to validate as non-. - The name of the parameter with which corresponds. - - - - Throws an . - - The name of the parameter that failed validation. - - - - A specialized implementation to be used with messenger types. - - The type of keys in the dictionary. - The type of values in the dictionary. - - - - The index indicating the start of a free linked list. - - - - - The array of 1-based indices for the items stored in . - - - - - The array of currently stored key-value pairs (ie. the lists for each hash group). - - - - - A coefficient used to speed up retrieving the target bucket when doing lookups. - - - - - The current number of items stored in the map. - - - - - The 1-based index for the start of the free list within . - - - - - The total number of empty items. - - - - - Initializes a new instance of the class. - - - - - - - - - - - - - - Checks whether or not the dictionary contains a pair with a specified key. - - The key to look for. - Whether or not the key was present in the dictionary. - - - - Gets the value if present for the specified key. - - The key to look for. - The value found, otherwise . - Whether or not the key was present. - - - - - - - Gets the value for the specified key, or, if the key is not present, - adds an entry and returns the value by ref. This makes it possible to - add or update a value in a single look up operation. - - Key to look for. - Reference to the new or existing value. - - - - - - - Enumerator for . - - - - - The entries being enumerated. - - - - - The current enumeration index. - - - - - The current dictionary count. - - - - - Creates a new instance. - - The input dictionary to enumerate. - - - - - - - Gets the current key. - - - - - Gets the current value. - - - - - Gets the value for the specified key, or. - - Key to look for. - Reference to the existing value. - - - - Initializes the current instance. - - The target capacity. - - - - - Resizes the current dictionary to reduce the number of collisions - - - - - Gets a reference to a target bucket from an input hashcode. - - The input hashcode. - A reference to the target bucket. - - - - A type representing a map entry, ie. a node in a given list. - - - - - The cached hashcode for ; - - - - - 0-based index of next entry in chain: -1 means end of chain - also encodes whether this entry this.itself_ is part of the free list by changing sign and subtracting 3, - so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc. - - - - - The key for the value in the current node. - - - - - The value in the current node, if present. - - - - - Throws an when trying to load an element with a missing key. - - - - - A helper class for . - - - - - Maximum prime smaller than the maximum array length. - - - - - An arbitrary prime factor used in . - - - - - Table of prime numbers to use as hash table sizes. - - - - - Checks whether a value is a prime. - - The value to check. - Whether or not is a prime. - - - - Gets the smallest prime bigger than a specified value. - - The target minimum value. - The new prime that was found. - - - - Returns size of hashtable to grow to. - - The previous table size. - The expanded table size. - - - - Returns approximate reciprocal of the divisor: ceil(2**64 / divisor). - - This should only be used on 64-bit. - - - - Performs a mod operation using the multiplier pre-computed with . - - This should only be used on 64-bit. - - - - A base interface masking instances and exposing non-generic functionalities. - - - - - Gets the count of entries in the dictionary. - - - - - Clears the current dictionary. - - - - - An interface providing key type contravariant and value type covariant access - to a instance. - - The contravariant type of keys in the dictionary. - The covariant type of values in the dictionary. - - - - Gets the value with the specified key. - - The key to look for. - The returned value. - Thrown if the key wasn't present. - - - - An interface providing key type contravariant access to a instance. - - The contravariant type of keys in the dictionary. - - - - Tries to remove a value with a specified key, if present. - - The key of the value to remove. - Whether or not the key was present. - - - - Schedules a callback roughly every gen 2 GC (you may see a Gen 0 an Gen 1 but only once). - Ported from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Gen2GcCallback.cs. - - - - - The callback to invoke at each GC. - - - - - A weak to the target object to pass to . - - - - - Initializes a new instance of the class. - - The callback to invoke at each GC. - The target object to pass as argument to . - - - - Schedules a callback to be called on each GC until the target is collected. - - The callback to invoke at each GC. - The target object to pass as argument to . - - - - Finalizes an instance of the class. - This finalizer is re-registered with as long as - the target object is alive, which means it will be executed again every time a generation 2 - collection is triggered (as the instance itself would be moved to - that generation after surviving the generation 0 and 1 collections the first time). - - - - - A custom instance that is specifically optimized to be used - by . In particular, it offers zero-allocation enumeration of stored items. - - Tke key of items to store in the table. - The values to store in the table. - - - - Initial length of the table. Must be a power of two. - - - - - This lock protects all mutation of data in the table. Readers do not take this lock. - - - - - The actual storage for the table; swapped out as the table grows. - - - - - Initializes a new instance of the class. - - - - - - - - Tries to add a new pair to the table. - - The key to add. - The value to associate with key. - - - - - - - - - - Implements the functionality for under a lock. - - The input key. - The callback to use to create a new item. - The new item to store. - - - - - - - Provides an enumerator for the current instance. - - - - - Parent table, set to null when disposed. - - - - - Last index in the container that should be enumerated. - - - - - The current index into the container. - - - - - The current key, if available. - - - - - The current value, if available. - - - - - Initializes a new instance of the class. - - The input instance being enumerated. - - - - - - - - - - Gets the current key. - - - - - Gets the current value. - - - - - Worker for adding a new key/value pair. Will resize the container if it is full. - - The key for the new entry. - The value for the new entry. - - - - A single entry within a instance. - - - - - Holds key and value using a weak reference for the key and a strong reference for the - value that is traversed only if the key is reachable without going through the value. - - - - - Cached copy of key's hashcode. - - - - - Index of next entry, -1 if last. - - - - - Container holds the actual data for the table. A given instance of Container always has the same capacity. When we need - more capacity, we create a new Container, copy the old one into the new one, and discard the old one. This helps enable - lock-free reads from the table, as readers never need to deal with motion of entries due to rehashing. - - - - - The with which this container is associated. - - - - - buckets[hashcode & (buckets.Length - 1)] contains index of the first entry in bucket (-1 if empty). - - - - - The table entries containing the stored dependency handles - - - - - firstFreeEntry < entries.Length => table has capacity, entries grow from the bottom of the table. - - - - - Flag detects if OOM or other background exception threw us out of the lock. - - - - - Set to true when initially finalized - - - - - Used to ensure the next allocated container isn't finalized until this one is GC'd. - - - - - Initializes a new instance of the class. - - The input object associated with the current instance. - - - - Initializes a new instance of the class. - - The input object associated with the current instance. - The array of buckets. - The array of entries. - The index of the first free entry. - - - - Gets the capacity of the current container. - - - - - Gets the index of the first free entry. - - - - - Worker for adding a new key/value pair. Container must NOT be full. - - - - - Worker for finding a key/value pair. Must hold lock. - - - - - Returns -1 if not found (if key expires during FindEntry, this can be treated as "not found."). - Must hold lock, or be prepared to retry the search while holding lock. - - This method requires to be on the stack to be properly tracked. - - - - Gets the entry at the specified entry index. - - - - - Removes the specified key from the table, if it exists. - - - - - Removes a given entry at a specified index. - - The index of the entry to remove. - - - - Resize, and scrub expired keys off bucket lists. Must hold . - - - is less than entries.Length on exit, that is, the table has at least one free entry. - - - - - Creates a new of a specified size with the current items. - - The new requested size. - The new instance with the requested size. - - - - Verifies that the current instance is valid. - - Thrown if the current instance is invalid. - - - - Finalizes the current instance. - - - - diff --git a/_dist/nextcloud/Nextcloud.deps.json b/_dist/nextcloud/Nextcloud.deps.json index e3eb6c8..575dce6 100644 --- a/_dist/nextcloud/Nextcloud.deps.json +++ b/_dist/nextcloud/Nextcloud.deps.json @@ -15,8 +15,7 @@ "Markdown.Avalonia": "11.0.2", "Newtonsoft.Json": "13.0.3", "RestSharp": "112.1.0", - "Shared": "1.0.0", - "CommunityToolkit.Mvvm": "8.3.0.0" + "Shared": "1.0.0" }, "runtime": { "Nextcloud.dll": {} @@ -88,6 +87,14 @@ } }, "Avalonia.BuildServices/0.0.29": {}, + "Avalonia.Controls.Recycling.Model/11.2.0": { + "runtime": { + "lib/net8.0/Avalonia.Controls.Recycling.Model.dll": { + "assemblyVersion": "11.2.0.0", + "fileVersion": "11.2.0.0" + } + } + }, "Avalonia.ReactiveUI/11.2.0": { "dependencies": { "Avalonia": "11.2.0", @@ -228,6 +235,37 @@ } } }, + "CommunityToolkit.Mvvm/8.0.0": { + "runtime": { + "lib/net6.0/CommunityToolkit.Mvvm.dll": { + "assemblyVersion": "8.0.0.0", + "fileVersion": "8.0.0.1" + } + } + }, + "Dock.Model/11.2.0": { + "dependencies": { + "Avalonia.Controls.Recycling.Model": "11.2.0" + }, + "runtime": { + "lib/net8.0/Dock.Model.dll": { + "assemblyVersion": "11.2.0.0", + "fileVersion": "11.2.0.0" + } + } + }, + "Dock.Model.Mvvm/11.2.0": { + "dependencies": { + "CommunityToolkit.Mvvm": "8.0.0", + "Dock.Model": "11.2.0" + }, + "runtime": { + "lib/net8.0/Dock.Model.Mvvm.dll": { + "assemblyVersion": "11.2.0.0", + "fileVersion": "11.2.0.0" + } + } + }, "DynamicData/8.4.1": { "dependencies": { "System.Reactive": "6.0.1" @@ -347,25 +385,6 @@ } } }, - "NP.Ava.UniDockService/1.0.6": { - "dependencies": { - "NP.Utilities": "1.0.30" - }, - "runtime": { - "lib/net8.0/NP.Ava.UniDockService.dll": { - "assemblyVersion": "1.0.6.0", - "fileVersion": "1.0.6.0" - } - } - }, - "NP.Utilities/1.0.30": { - "runtime": { - "lib/net8.0/NP.Utilities.dll": { - "assemblyVersion": "1.0.30.0", - "fileVersion": "1.0.30.0" - } - } - }, "ReactiveUI/20.1.1": { "dependencies": { "DynamicData": "8.4.1", @@ -531,15 +550,7 @@ "System.Runtime": "4.3.0" } }, - "System.ValueTuple/4.5.0": {}, - "CommunityToolkit.Mvvm/8.3.0.0": { - "runtime": { - "CommunityToolkit.Mvvm.dll": { - "assemblyVersion": "8.3.0.0", - "fileVersion": "8.3.2.1" - } - } - } + "System.ValueTuple/4.5.0": {} } }, "libraries": { @@ -569,6 +580,13 @@ "path": "avalonia.buildservices/0.0.29", "hashPath": "avalonia.buildservices.0.0.29.nupkg.sha512" }, + "Avalonia.Controls.Recycling.Model/11.2.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-QSvLVBhBWGZvmX4dZu5gNaTHfOkh+CtwT2fvM1WnroG2zKdpev00M3U+/x+o9wuWR+FDFodqfIsDHU/s3w6Q1A==", + "path": "avalonia.controls.recycling.model/11.2.0", + "hashPath": "avalonia.controls.recycling.model.11.2.0.nupkg.sha512" + }, "Avalonia.ReactiveUI/11.2.0": { "type": "package", "serviceable": true, @@ -653,6 +671,27 @@ "path": "colortextblock.avalonia/11.0.2", "hashPath": "colortextblock.avalonia.11.0.2.nupkg.sha512" }, + "CommunityToolkit.Mvvm/8.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Jiu2g5WUdXRwzhJkHB+B4JBKP5A5+fp8xKiW/ZQo5PI+DruI7MbPEcK9K/Aw0YzTiWRuG6CBluzYIWN5Eo7BkQ==", + "path": "communitytoolkit.mvvm/8.0.0", + "hashPath": "communitytoolkit.mvvm.8.0.0.nupkg.sha512" + }, + "Dock.Model/11.2.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-vvgwgCr3IXq3LQQTXiaEeoWPkze31HJxTdEWw8cv84VECHIgH4TiPN1l3P+6u8fKT+4V8cgC1rD8Z4nHUQFkcA==", + "path": "dock.model/11.2.0", + "hashPath": "dock.model.11.2.0.nupkg.sha512" + }, + "Dock.Model.Mvvm/11.2.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-XbE5W4Dm+YcN5xfKW3V9NyHNiwev3WYlmWdskx5sO2oFMUuVizyWvwz6JyyqjXadI86tVxi+a9DlsyuPkHCNuA==", + "path": "dock.model.mvvm/11.2.0", + "hashPath": "dock.model.mvvm.11.2.0.nupkg.sha512" + }, "DynamicData/8.4.1": { "type": "package", "serviceable": true, @@ -744,20 +783,6 @@ "path": "newtonsoft.json/13.0.3", "hashPath": "newtonsoft.json.13.0.3.nupkg.sha512" }, - "NP.Ava.UniDockService/1.0.6": { - "type": "package", - "serviceable": true, - "sha512": "sha512-GHS67athB7fd/qvHJOEbYJUtJjKjjqf0sVcF1iB0CxqNrKgG5LPGzGyCdynYsy+gi7SqO29S+eqQK+3E9D7Mrw==", - "path": "np.ava.unidockservice/1.0.6", - "hashPath": "np.ava.unidockservice.1.0.6.nupkg.sha512" - }, - "NP.Utilities/1.0.30": { - "type": "package", - "serviceable": true, - "sha512": "sha512-yNvPMvlhuh8oYt9qYOoGC650uhe/lSleKI6RV7hEOyLWiah8NgPXwdj2GquR9ySCtWefjPkHYwTUDRwP0hw0ZQ==", - "path": "np.utilities/1.0.30", - "hashPath": "np.utilities.1.0.30.nupkg.sha512" - }, "ReactiveUI/20.1.1": { "type": "package", "serviceable": true, @@ -918,11 +943,6 @@ "sha512": "sha512-okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==", "path": "system.valuetuple/4.5.0", "hashPath": "system.valuetuple.4.5.0.nupkg.sha512" - }, - "CommunityToolkit.Mvvm/8.3.0.0": { - "type": "reference", - "serviceable": false, - "sha512": "" } } } \ No newline at end of file diff --git a/_dist/nextcloud/Nextcloud.dll b/_dist/nextcloud/Nextcloud.dll index 3ba7c3e..a608a67 100644 Binary files a/_dist/nextcloud/Nextcloud.dll and b/_dist/nextcloud/Nextcloud.dll differ diff --git a/_dist/nextcloud/Nextcloud.pdb b/_dist/nextcloud/Nextcloud.pdb index 3614b58..28ccad7 100644 Binary files a/_dist/nextcloud/Nextcloud.pdb and b/_dist/nextcloud/Nextcloud.pdb differ