From c3a965875f66ef9c8a9308d245e0029a5c199dc5 Mon Sep 17 00:00:00 2001 From: Jonas Arnold Date: Sat, 25 Mar 2023 12:31:33 +0100 Subject: [PATCH] added SendReceiveViewModel and according View, moved StartupHelpers to new Common project, added TabControl to ShellView --- Common/Common.csproj | 13 ++++++++ Common/StartupHelpers/AbstractFactory.cs | 24 ++++++++++++++ Common/StartupHelpers/IAbstractFactory.cs | 6 ++++ Common/StartupHelpers/ServiceExtensions.cs | 22 +++++++++++++ MultiTerm.Core/MultiTerm.Core.csproj | 4 +++ .../ViewModel/ITerminalViewModel.cs | 8 +++++ .../ViewModel/SendReceiveViewModel.cs | 10 ++++++ MultiTerm.Core/ViewModel/ShellViewModel.cs | 31 ++++++++++++++++++- MultiTerm.Core/ViewModel/TerminalViewModel.cs | 8 +++++ MultiTerm.Wpf/App.xaml.cs | 4 +++ MultiTerm.Wpf/MultiTerm.Wpf.csproj | 1 + MultiTerm.Wpf/View/SendReceiveView.xaml | 12 +++++++ MultiTerm.Wpf/View/SendReceiveView.xaml.cs | 11 +++++++ MultiTerm.Wpf/View/ShellView.xaml | 21 ++++++++++++- MultiTerm.sln | 10 ++++-- 15 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 Common/Common.csproj create mode 100644 Common/StartupHelpers/AbstractFactory.cs create mode 100644 Common/StartupHelpers/IAbstractFactory.cs create mode 100644 Common/StartupHelpers/ServiceExtensions.cs create mode 100644 MultiTerm.Core/ViewModel/ITerminalViewModel.cs create mode 100644 MultiTerm.Core/ViewModel/SendReceiveViewModel.cs create mode 100644 MultiTerm.Core/ViewModel/TerminalViewModel.cs create mode 100644 MultiTerm.Wpf/View/SendReceiveView.xaml create mode 100644 MultiTerm.Wpf/View/SendReceiveView.xaml.cs 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