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 @@
-
+
+
+
+
@@ -875,7 +314,15 @@
1732644534156
-
+
+
+ 1732816975736
+
+
+
+ 1732816975736
+
+
@@ -896,9 +343,9 @@
-
-
+
+
@@ -1001,95 +448,17 @@
- file://$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs
- 43
-
+ file://$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/ViewModels/MainDockWindowViewModel.cs
+ 113
+
-
+
-
+
-
-
-
- file://$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs
- 50
-
-
-
-
-
-
-
-
-
-
-
- file://$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs
- 60
-
-
-
-
-
-
-
-
-
-
-
- file://$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs
- 62
-
-
-
-
-
-
-
-
-
-
-
- file://$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs
- 64
-
-
-
-
-
-
-
-
-
-
-
- file://$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs
- 67
-
-
-
-
-
-
-
-
-
-
-
- file://$PROJECT_DIR$/PSCHelpdesk/PSCHelpdesk/Views/MainDockWindow.axaml.cs
- 75
-
-
-
-
-
-
-
-
-
+
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 @@
ForceIncludedForceIncluded
+ ForceIncludedForceIncludedForceIncludedForceIncluded
@@ -21,10 +22,13 @@
ForceIncludedForceIncludedForceIncluded
+ ForceIncludedForceIncludedForceIncludedForceIncludedForceIncluded
+ ForceIncluded
+ ForceIncludedForceIncludedForceIncludedForceIncluded
@@ -33,6 +37,8 @@
ForceIncludedForceIncludedForceIncluded
+ ForceIncluded
+ ForceIncludedForceIncludedForceIncludedForceIncluded
@@ -43,6 +49,7 @@
ForceIncludedForceIncludedForceIncluded
+ ForceIncludedForceIncludedForceIncludedForceIncluded
@@ -58,6 +65,7 @@
ForceIncludedForceIncludedForceIncluded
+ ForceIncludedForceIncludedForceIncludedForceIncluded
@@ -91,6 +99,7 @@
ForceIncludedForceIncludedForceIncluded
+ ForceIncludedTrue<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.axamlCode
-
- 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