diff --git a/Common/Common.csproj b/Common/Common.csproj
new file mode 100644
index 0000000..345380b
--- /dev/null
+++ b/Common/Common.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/Common/StartupHelpers/AbstractFactory.cs b/Common/StartupHelpers/AbstractFactory.cs
new file mode 100644
index 0000000..84cefe8
--- /dev/null
+++ b/Common/StartupHelpers/AbstractFactory.cs
@@ -0,0 +1,24 @@
+namespace Common.StartupHelpers;
+
+public class AbstractFactory : IAbstractFactory
+{
+ private readonly Func factory;
+
+ ///
+ /// Constructor for Abstract Factory.
+ ///
+ /// Function of the factory
+ public AbstractFactory(Func factory)
+ {
+ this.factory = factory;
+ }
+
+ ///
+ /// Executes factory function and returns it.
+ ///
+ /// Factory
+ public T Create()
+ {
+ return factory();
+ }
+}
\ No newline at end of file
diff --git a/Common/StartupHelpers/IAbstractFactory.cs b/Common/StartupHelpers/IAbstractFactory.cs
new file mode 100644
index 0000000..7f4cbc9
--- /dev/null
+++ b/Common/StartupHelpers/IAbstractFactory.cs
@@ -0,0 +1,6 @@
+namespace Common.StartupHelpers;
+
+public interface IAbstractFactory
+{
+ T Create();
+}
\ No newline at end of file
diff --git a/Common/StartupHelpers/ServiceExtensions.cs b/Common/StartupHelpers/ServiceExtensions.cs
new file mode 100644
index 0000000..f4493e1
--- /dev/null
+++ b/Common/StartupHelpers/ServiceExtensions.cs
@@ -0,0 +1,22 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Common.StartupHelpers;
+
+public static class ServiceExtensions
+{
+ ///
+ /// Adds a factory for subcontrols to be created.
+ /// For example a UserControl can be instanciated using this Service.
+ ///
+ /// type of the subcontrol
+ /// existing service collection
+ public static void AddSubControlFactory(this IServiceCollection services) where TSubControl : class
+ {
+ // add to DI: the subcontrol itself
+ services.AddTransient();
+ // add to DI: Func of that subcontrol, that will create the subcontrol
+ services.AddSingleton>(x => () => x.GetService()!);
+ // add to DI: Factory for the subcontrol
+ services.AddSingleton, AbstractFactory>();
+ }
+}
diff --git a/MultiTerm.Core/MultiTerm.Core.csproj b/MultiTerm.Core/MultiTerm.Core.csproj
index 80ca023..261ea41 100644
--- a/MultiTerm.Core/MultiTerm.Core.csproj
+++ b/MultiTerm.Core/MultiTerm.Core.csproj
@@ -14,4 +14,8 @@
+
+
+
+
diff --git a/MultiTerm.Core/ViewModel/ITerminalViewModel.cs b/MultiTerm.Core/ViewModel/ITerminalViewModel.cs
new file mode 100644
index 0000000..4902a92
--- /dev/null
+++ b/MultiTerm.Core/ViewModel/ITerminalViewModel.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace MultiTerm.Core.ViewModel;
+
+public interface ITerminalViewModel
+{
+ string Title { get; }
+}
diff --git a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs
new file mode 100644
index 0000000..7e4b60a
--- /dev/null
+++ b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs
@@ -0,0 +1,10 @@
+using System;
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace MultiTerm.Core.ViewModel;
+
+[ObservableObject]
+public partial class SendReceiveViewModel : TerminalViewModel
+{
+ public override string Title => "SendReceive Tab";
+}
diff --git a/MultiTerm.Core/ViewModel/ShellViewModel.cs b/MultiTerm.Core/ViewModel/ShellViewModel.cs
index 1aafa2b..770fe1a 100644
--- a/MultiTerm.Core/ViewModel/ShellViewModel.cs
+++ b/MultiTerm.Core/ViewModel/ShellViewModel.cs
@@ -1,9 +1,38 @@
-using CommunityToolkit.Mvvm.ComponentModel;
+using Common.StartupHelpers;
+using CommunityToolkit.Mvvm.ComponentModel;
+using System.Collections.ObjectModel;
namespace MultiTerm.Core.ViewModel;
public partial class ShellViewModel : ObservableObject
{
+ private readonly IAbstractFactory sendReceiveViewModelFactory;
+
[ObservableProperty]
private string title = "ShellView Test";
+
+ [ObservableProperty]
+ private ObservableCollection terminalViewModels = new();
+
+ [ObservableProperty]
+ private ITerminalViewModel? selectedTerminalViewModel;
+
+ public ShellViewModel(IAbstractFactory sendReceiveViewModelFactory)
+ {
+ this.sendReceiveViewModelFactory = sendReceiveViewModelFactory;
+ // create a new terminal
+ this.AppendTerminal(this.sendReceiveViewModelFactory.Create());
+ }
+
+ public void AppendTerminal(ITerminalViewModel newTerminal)
+ {
+ // guard null value
+ if(newTerminal == null)
+ {
+ return;
+ }
+ // add to collection and set as selected
+ this.TerminalViewModels.Add(newTerminal);
+ this.SelectedTerminalViewModel = newTerminal;
+ }
}
diff --git a/MultiTerm.Core/ViewModel/TerminalViewModel.cs b/MultiTerm.Core/ViewModel/TerminalViewModel.cs
new file mode 100644
index 0000000..08feb2d
--- /dev/null
+++ b/MultiTerm.Core/ViewModel/TerminalViewModel.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace MultiTerm.Core.ViewModel;
+
+public abstract class TerminalViewModel : ITerminalViewModel
+{
+ public abstract string Title { get; }
+}
diff --git a/MultiTerm.Wpf/App.xaml.cs b/MultiTerm.Wpf/App.xaml.cs
index a96cd2b..406f307 100644
--- a/MultiTerm.Wpf/App.xaml.cs
+++ b/MultiTerm.Wpf/App.xaml.cs
@@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MultiTerm.Core.ViewModel;
+using Common.StartupHelpers;
using System.Windows;
namespace MultiTerm.Wpf;
@@ -19,6 +20,9 @@ public partial class App : Application
// viewmodels
services.AddSingleton();
+
+ // subcontrols
+ services.AddSubControlFactory();
})
.Build();
}
diff --git a/MultiTerm.Wpf/MultiTerm.Wpf.csproj b/MultiTerm.Wpf/MultiTerm.Wpf.csproj
index 4137eaf..1ee0ac4 100644
--- a/MultiTerm.Wpf/MultiTerm.Wpf.csproj
+++ b/MultiTerm.Wpf/MultiTerm.Wpf.csproj
@@ -13,6 +13,7 @@
+
diff --git a/MultiTerm.Wpf/View/SendReceiveView.xaml b/MultiTerm.Wpf/View/SendReceiveView.xaml
new file mode 100644
index 0000000..f3611c1
--- /dev/null
+++ b/MultiTerm.Wpf/View/SendReceiveView.xaml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/MultiTerm.Wpf/View/SendReceiveView.xaml.cs b/MultiTerm.Wpf/View/SendReceiveView.xaml.cs
new file mode 100644
index 0000000..e840f2d
--- /dev/null
+++ b/MultiTerm.Wpf/View/SendReceiveView.xaml.cs
@@ -0,0 +1,11 @@
+using System.Windows.Controls;
+
+namespace MultiTerm.Wpf.View;
+
+public partial class SendReceiveView : UserControl
+{
+ public SendReceiveView()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/MultiTerm.Wpf/View/ShellView.xaml b/MultiTerm.Wpf/View/ShellView.xaml
index c3f54b9..7b340e1 100644
--- a/MultiTerm.Wpf/View/ShellView.xaml
+++ b/MultiTerm.Wpf/View/ShellView.xaml
@@ -4,9 +4,28 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MultiTerm.Wpf.View"
+ xmlns:vm="clr-namespace:MultiTerm.Core.ViewModel;assembly=MultiTerm.Core"
+ xmlns:v="clr-namespace:MultiTerm.Wpf.View"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MultiTerm.sln b/MultiTerm.sln
index 0117aae..7ccc151 100644
--- a/MultiTerm.sln
+++ b/MultiTerm.sln
@@ -3,9 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33424.131
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultiTerm.Wpf", "MultiTerm.Wpf\MultiTerm.Wpf.csproj", "{1C18608F-596A-47ED-9BD6-96E5E52E6E88}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiTerm.Wpf", "MultiTerm.Wpf\MultiTerm.Wpf.csproj", "{1C18608F-596A-47ED-9BD6-96E5E52E6E88}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultiTerm.Core", "MultiTerm.Core\MultiTerm.Core.csproj", "{A4ED5CBB-954E-4F23-B9CB-8E30DF7B8F48}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiTerm.Core", "MultiTerm.Core\MultiTerm.Core.csproj", "{A4ED5CBB-954E-4F23-B9CB-8E30DF7B8F48}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{26454190-1B60-46BE-8234-3207FB00D8A4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +23,10 @@ Global
{A4ED5CBB-954E-4F23-B9CB-8E30DF7B8F48}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4ED5CBB-954E-4F23-B9CB-8E30DF7B8F48}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4ED5CBB-954E-4F23-B9CB-8E30DF7B8F48}.Release|Any CPU.Build.0 = Release|Any CPU
+ {26454190-1B60-46BE-8234-3207FB00D8A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {26454190-1B60-46BE-8234-3207FB00D8A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {26454190-1B60-46BE-8234-3207FB00D8A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {26454190-1B60-46BE-8234-3207FB00D8A4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE