diff --git a/.gitignore b/.gitignore
index 00022acfc..3716c2a5a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,22 +6,29 @@
*.exe
*.dll
*.bak
+*.user
+*.bak
/.svn
/.vs
/bin
+/obj
+/obj.net
/*/.vs
-/CSharpBible/*/.vs
/*/obj
/*/bin
/*/TestResults
/*/*/TestResults
+/*/*/.vs
/*/*/obj
/*/*/bin
/*/*/*/.vs
/*/*/*/obj
/*/*/*/bin
+/*/*/*/TestResults
/CSharpBible/Help
/CSharpBible/Mobile
+/CSharpBible/Web
+/CSharpBible/WinUI
/CSharpBible/AboutEx/obj
/CSharpBible/AboutEx/publish
/CSharpBible/AboutExTests/bin
@@ -42,9 +49,12 @@
/CSharpBible/CSV_ViewerTest/obj
/CSharpBible/ConsoleMouseApp/obj
/CSharpBible/ConsoleLib/obj
+/CSharpBible/DB/ADO_Test
/CSharpBible/DataGridEx/obj
/CSharpBible/DataGridExWPF/obj
/CSharpBible/packages
+/CSharpBible/Basics/.vs
+/CSharpBible/Basics/.vs
/NUnitTestProject1/NUnitTestProject1/obj
/TestStatements/.vs
/TestStatements/AsyncExample/obj
@@ -66,21 +76,6 @@
/CSharpProgrammierHandbuch/Fibonacci2
/TestStatements/AsyncExampleWPF
/TestStatements/Tutorials/obj/Debug
-/CSharpBible/Basics/.vs
-/CSharpBible/Basics/.vs
-*.user
-*.bak
-/CSharpBible/Calc/.vs
-/CSharpBible/DB/.vs
-/CSharpBible/Mobile
-/CSharpBible/MVVM_Tutorial/.vs
-/CSharpBible/Calc/Help
-/CSharpBible/DependencyInjection/.vs
-/CSharpBible/CSharpBibleTest/.vs
-/CSharpBible/Games/.vs
-/CSharpBible/Graphics/.vs
-/GenFreeWin/.vs
-/JC-AMS/.vs
/obj
/obj.net
/TestStatements/Help
diff --git a/CSharpBible/ConsoleDisplay/View/ITileDef.cs b/CSharpBible/ConsoleDisplay/View/ITileDef.cs
new file mode 100644
index 000000000..835b61148
--- /dev/null
+++ b/CSharpBible/ConsoleDisplay/View/ITileDef.cs
@@ -0,0 +1,25 @@
+// ***********************************************************************
+// Assembly : ConsoleDisplay
+// Author : Mir
+// Created : 08-19-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 08-27-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using System;
+using System.Drawing;
+
+namespace ConsoleDisplay.View
+{
+ public interface ITileDef
+ {
+ Size TileSize { get; }
+
+ (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile);
+ }
+}
\ No newline at end of file
diff --git a/CSharpBible/ConsoleDisplay/View/Interfaces/IConsole.cs b/CSharpBible/ConsoleDisplay/View/Interfaces/IConsole.cs
new file mode 100644
index 000000000..ac7df635c
--- /dev/null
+++ b/CSharpBible/ConsoleDisplay/View/Interfaces/IConsole.cs
@@ -0,0 +1,39 @@
+// ***********************************************************************
+// Assembly : ConsoleDisplay
+// Author : Mir
+// Created : 07-16-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 07-24-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using System;
+
+namespace ConsoleDisplay.View
+{
+ public interface IConsole
+ {
+ ConsoleColor ForegroundColor { get; set; }
+ ConsoleColor BackgroundColor { get; set; }
+ bool IsOutputRedirected { get; }
+ bool KeyAvailable { get; }
+ int LargestWindowHeight { get; }
+ string Title { get; set; }
+ int WindowHeight { get; set; }
+ int WindowWidth { get; set; }
+
+ void Beep(int freq, int len);
+ void Clear();
+ (int Left, int Top) GetCursorPosition();
+ ConsoleKeyInfo? ReadKey();
+ string ReadLine();
+ void SetCursorPosition(int left, int top);
+ void Write(char ch);
+ void Write(string? st);
+ void WriteLine(string? st = "");
+ }
+}
\ No newline at end of file
diff --git a/CSharpBible/ConsoleDisplay/View/Interfaces/ITileDisplay.cs b/CSharpBible/ConsoleDisplay/View/Interfaces/ITileDisplay.cs
new file mode 100644
index 000000000..faa64df4a
--- /dev/null
+++ b/CSharpBible/ConsoleDisplay/View/Interfaces/ITileDisplay.cs
@@ -0,0 +1,36 @@
+// ***********************************************************************
+// Assembly : ConsoleDisplay
+// Author : Mir
+// Created : 08-19-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 08-27-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using System;
+using System.Drawing;
+
+namespace ConsoleDisplay.View
+{
+ public interface ITileDisplay
+ {
+ T? this[Point Idx] { get; set; }
+
+ Point Position { get; }
+ Size DispSize { get; }
+ Size TileSize { get; }
+ IConsole console { get; }
+ Point DispOffset { get; set; }
+ Func? FncGetTile { get; set; }
+ Func? FncOldPos { get; set; }
+
+ void FullRedraw();
+ void SetDispSize(Size size);
+ void Update(bool e);
+ void WriteTile(PointF p, T tile);
+ }
+}
\ No newline at end of file
diff --git a/CSharpBible/ConsoleDisplay/View/TileDefBase.cs b/CSharpBible/ConsoleDisplay/View/TileDefBase.cs
index 46c2fb1a2..f3539e4ab 100644
--- a/CSharpBible/ConsoleDisplay/View/TileDefBase.cs
+++ b/CSharpBible/ConsoleDisplay/View/TileDefBase.cs
@@ -19,7 +19,7 @@ namespace ConsoleDisplay.View {
/// Class TileDef.
///
/// The type of the enum.
- public abstract class TileDefBase
+ public abstract class TileDefBase : ITileDef
{
///
/// Gets the tile definition.
diff --git a/CSharpBible/ConsoleDisplay/View/TileDisplay.cs b/CSharpBible/ConsoleDisplay/View/TileDisplay.cs
index 4ce2ccf71..efbe8db75 100644
--- a/CSharpBible/ConsoleDisplay/View/TileDisplay.cs
+++ b/CSharpBible/ConsoleDisplay/View/TileDisplay.cs
@@ -63,7 +63,7 @@ public class TileDisplay: ITileDisplay
/// it returns the default-tileDef when the local tileDef isn't set.
///
/// The tile definition.
- public TileDefBase? TileDef { get => _tileDef ?? tileDef; set => _tileDef = value; }
+ public ITileDef? TileDef { get => _tileDef ?? tileDef; set => _tileDef = value; }
public Point DispOffset { get; set; } = Point.Empty;
public Func? FncGetTile { get; set; }
@@ -96,7 +96,7 @@ public class TileDisplay: ITileDisplay
///
/// The (local) tile-definition
///
- private TileDefBase? _tileDef;
+ private ITileDef? _tileDef;
#endregion
#endregion
@@ -154,29 +154,20 @@ private static void WriteTileChunk(IConsole console,Point Offset, PointF p, (str
///
/// Initializes a new instance of the class.
///
- public TileDisplay() : this(new MyConsole(),Point.Empty,Size.Empty){}
+ public TileDisplay() : this(new MyConsole(),tileDef!,Point.Empty,Size.Empty){}
///
/// Initializes a new instance of the class.
///
- public TileDisplay(IConsole console) : this(console, Point.Empty, Size.Empty) { }
+ public TileDisplay(IConsole console,ITileDef tileDef) : this(console, tileDef, Point.Empty, Size.Empty) { }
///
/// Initializes a new instance of the class.
///
/// The position.
/// The size.
- public TileDisplay(IConsole console,Point position, Size size) : this(console, position, size,tileDef?.TileSize ?? new Size(4,2)) { }
+ public TileDisplay(IConsole console, ITileDef tileDef, Point position, Size size) : this(console, tileDef, position, size,tileDef?.TileSize ?? new Size(4,2)) { }
- ///
- /// Initializes a new instance of the class.
- ///
- /// The position.
- /// The size.
- /// The tile-definition.
- public TileDisplay(IConsole console,Point position, Size size, TileDefBase aTileDef) : this(console,position, size, aTileDef.TileSize ) {
- TileDef = aTileDef;
- }
///
/// Initializes a new instance of the class.
@@ -184,16 +175,23 @@ public TileDisplay(IConsole console,Point position, Size size, TileDefBase aTile
/// The position.
/// The size.
/// Size of the tile.
- public TileDisplay(IConsole console,Point position,Size size, Size tileSize)
+ public TileDisplay(IConsole console, ITileDef tileDef, Point position,Size size, Size tileSize)
{
this.console = console;
+ _tileDef = tileDef;
_rect.Location = position;
_tileSize = tileSize != Size.Empty ? tileSize : new Size(4, 2);
+ SetDispSize(size);
+ }
+
+ public void SetDispSize(Size size)
+ {
if (size == Size.Empty)
- _size = new Size(console.WindowWidth / _tileSize.Width,console.WindowHeight/_tileSize.Height);
+ _size = new Size(console.WindowWidth / _tileSize.Width, console.WindowHeight / _tileSize.Height);
else
_size = size;
- _rect.Size = new Size(_size.Width * _tileSize.Width,_size.Height * _tileSize.Height);
+ _rect.Size = new Size(_size.Width * _tileSize.Width, _size.Height * _tileSize.Height);
+ _changed = true;
}
#region private Methods
@@ -332,22 +330,15 @@ public TileDisplay() : base() { }
///
/// Initializes a new instance of the class.
///
- public TileDisplay(IConsole console) : base(console) { }
+ public TileDisplay(IConsole console, ITileDef tileDef) : base(console,tileDef) { }
///
/// Initializes a new instance of the class.
///
/// The position.
/// The size.
- public TileDisplay(IConsole console,Point position, Size size) : base(console, position, size) { }
+ public TileDisplay(IConsole console,ITileDef tileDef, Point position, Size size) : base(console, tileDef, position, size) { }
- ///
- /// Initializes a new instance of the class.
- ///
- /// The position.
- /// The size.
- /// The tile-definition.
- public TileDisplay(IConsole console, Point position, Size size, TileDefBase aTileDef) : base(console, position, size, aTileDef) { }
///
/// Initializes a new instance of the class.
@@ -355,5 +346,5 @@ public TileDisplay(IConsole console, Point position, Size size, TileDefBase aTil
/// The position.
/// The size.
/// Size of the tile.
- public TileDisplay(IConsole console, Point position, Size size, Size tileSize) : base(console, position, size, tileSize) { }
+ public TileDisplay(IConsole console, ITileDef tileDef, Point position, Size size, Size tileSize) : base(console, tileDef, position, size, tileSize) { }
}
diff --git a/CSharpBible/Games/CsEpiphany/Model/Direction.cs b/CSharpBible/Games/CsEpiphany/Model/Direction.cs
new file mode 100644
index 000000000..242ca2ade
--- /dev/null
+++ b/CSharpBible/Games/CsEpiphany/Model/Direction.cs
@@ -0,0 +1,10 @@
+namespace CsEpiphany.Model
+{
+ public enum Direction
+ {
+ UP,
+ DOWN,
+ RIGHT,
+ LEFT
+ }
+}
\ No newline at end of file
diff --git a/CSharpBible/Games/Game_Base/Helper/CRandom.cs b/CSharpBible/Games/Game_Base/Helper/CRandom.cs
new file mode 100644
index 000000000..5d2cfa3b7
--- /dev/null
+++ b/CSharpBible/Games/Game_Base/Helper/CRandom.cs
@@ -0,0 +1,22 @@
+using BaseLib.Interfaces;
+using System;
+
+namespace BaseLib.Helper;
+
+public class CRandom :IRandom
+{
+ private Random _random;
+
+ public CRandom()
+ {
+ _random = new Random();
+ }
+
+ public int Next(int v1, int v2) => v2 !=-1 || v1 _random.NextDouble();
+
+ public int NextInt() => _random.Next();
+
+ public void Seed(int value) => _random = new Random(value);
+}
diff --git a/CSharpBible/Games/Game_Base/Helper/SysTime.cs b/CSharpBible/Games/Game_Base/Helper/SysTime.cs
new file mode 100644
index 000000000..f580bbe9f
--- /dev/null
+++ b/CSharpBible/Games/Game_Base/Helper/SysTime.cs
@@ -0,0 +1,12 @@
+using BaseLib.Interfaces;
+using System;
+
+namespace BaseLib.Helper;
+
+public class SysTime : ISysTime
+{
+ public static Func GetNow {get; set;} = () => DateTime.Now;
+ public DateTime Now => GetNow();
+ public DateTime Today => GetNow().Date;
+
+}
diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/IHasValue.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/IHasValue.cs
new file mode 100644
index 000000000..55e76295e
--- /dev/null
+++ b/CSharpBible/Games/Game_Base/Model/Interfaces/IHasValue.cs
@@ -0,0 +1,6 @@
+namespace BaseLib.Interfaces;
+
+public interface IHasValue
+{
+ object? Value { get; }
+}
diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/ILog.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/ILog.cs
new file mode 100644
index 000000000..2f9c1cb91
--- /dev/null
+++ b/CSharpBible/Games/Game_Base/Model/Interfaces/ILog.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace BaseLib.Interfaces;
+
+public interface ILog
+{
+ public void Log(string message);
+
+ public void Log(string message, Exception exception);
+}
diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/IPlacedObject.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/IPlacedObject.cs
index caa665b35..d2b22b030 100644
--- a/CSharpBible/Games/Game_Base/Model/Interfaces/IPlacedObject.cs
+++ b/CSharpBible/Games/Game_Base/Model/Interfaces/IPlacedObject.cs
@@ -29,7 +29,7 @@ public interface IPlacedObject
///
/// Occurs when [on place change].
///
- event EventHandler<(Point oP, Point nP)> OnPlaceChange;
+ event EventHandler<(Point oP, Point nP)>? OnPlaceChange;
#if NET6_0_OR_GREATER
///
/// Gets or sets the place.
diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/IPlayfield2D.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/IPlayfield2D.cs
new file mode 100644
index 000000000..159a6d68d
--- /dev/null
+++ b/CSharpBible/Games/Game_Base/Model/Interfaces/IPlayfield2D.cs
@@ -0,0 +1,31 @@
+// ***********************************************************************
+// Assembly : Snake_Base
+// Author : Mir
+// Created : 08-24-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace Game_Base.Model;
+
+public interface IPlayfield2D where T : class
+{
+ T? this[Point p] { get;set; }
+
+ Size PfSize { get; set; }
+ Rectangle Rect { get; }
+ IEnumerable Items { get; }
+
+ event EventHandler<(string prop, object? oldVal, object? newVal)>? OnDataChanged;
+
+ bool IsInside(Point P);
+}
\ No newline at end of file
diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/IRandom.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/IRandom.cs
new file mode 100644
index 000000000..fcb45ab39
--- /dev/null
+++ b/CSharpBible/Games/Game_Base/Model/Interfaces/IRandom.cs
@@ -0,0 +1,46 @@
+// ***********************************************************************
+// Assembly : MVVM_BaseLib
+// Author : Mir
+// Created : 07-01-2024
+//
+// Last Modified By : Mir
+// Last Modified On : 07-01-2024
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+///
+/// The Interfaces namespace.
+///
+namespace BaseLib.Interfaces;
+
+///
+/// Interface IRandom
+///
+public interface IRandom
+{
+ ///
+ /// Gets the next random number between v1 and v2 if v2 is set, between 0 and v1 if v2 is not set.
+ ///
+ /// The first boarder
+ /// The second boarder
+ /// System.Int32.
+ int Next(int v1, int v2=-1);
+ ///
+ /// Gets the next random number as double between ]0 and 1[.
+ ///
+ /// System.Double.
+ double NextDouble();
+ ///
+ /// Gets the next random number as int.
+ ///
+ /// System.Int32.
+ int NextInt();
+ ///
+ /// Specifies the seed-value.
+ ///
+ /// The value.
+ void Seed(int value);
+}
diff --git a/CSharpBible/Games/Game_Base/Model/Interfaces/ISysTime.cs b/CSharpBible/Games/Game_Base/Model/Interfaces/ISysTime.cs
new file mode 100644
index 000000000..d74e68f63
--- /dev/null
+++ b/CSharpBible/Games/Game_Base/Model/Interfaces/ISysTime.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace BaseLib.Interfaces;
+
+public interface ISysTime
+{
+ DateTime Now { get; }
+ DateTime Today { get; }
+}
diff --git a/CSharpBible/Games/Games.sln b/CSharpBible/Games/Games.sln
index 0cd342ca4..b1ce1766e 100644
--- a/CSharpBible/Games/Games.sln
+++ b/CSharpBible/Games/Games.sln
@@ -113,6 +113,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VTileEdit", "VTileEdit\VTil
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Werner_Flaschbier_ConsoleTests", "Werner_Flaschbier_BaseTests\Werner_Flaschbier_ConsoleTests.csproj", "{2CA579B8-2C96-4CB8-8FC3-510B9C353BCD}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VTileEditTests", "VTileEditTests\VTileEditTests.csproj", "{AC41269E-DFCB-4656-BE50-AB6A7FABFB37}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -299,6 +301,10 @@ Global
{2CA579B8-2C96-4CB8-8FC3-510B9C353BCD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CA579B8-2C96-4CB8-8FC3-510B9C353BCD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CA579B8-2C96-4CB8-8FC3-510B9C353BCD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AC41269E-DFCB-4656-BE50-AB6A7FABFB37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AC41269E-DFCB-4656-BE50-AB6A7FABFB37}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AC41269E-DFCB-4656-BE50-AB6A7FABFB37}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AC41269E-DFCB-4656-BE50-AB6A7FABFB37}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/CSharpBible/Games/Snake_Base/Models/Apple.cs b/CSharpBible/Games/Snake_Base/Models/Apple.cs
new file mode 100644
index 000000000..fb7c3e772
--- /dev/null
+++ b/CSharpBible/Games/Snake_Base/Models/Apple.cs
@@ -0,0 +1,47 @@
+// ***********************************************************************
+// Assembly : Snake_Base
+// Author : Mir
+// Created : 08-25-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using Game_Base.Model;
+using Snake_Base.Models.Interfaces;
+using System.Drawing;
+
+///
+/// The Models namespace.
+///
+///
+namespace Snake_Base.Models
+{
+ ///
+ /// Class Apple.
+ /// Implements the
+ ///
+ ///
+ public class Apple : SnakeGameObject
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Apple():base()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The point.
+ /// The PLF.
+ public Apple(Point point, IPlayfield2D? plf = null) : base(point, plf)
+ {
+ }
+ }
+}
diff --git a/CSharpBible/Games/Snake_Base/Models/Data/SnakeTiles.cs b/CSharpBible/Games/Snake_Base/Models/Data/SnakeTiles.cs
new file mode 100644
index 000000000..0c5538fda
--- /dev/null
+++ b/CSharpBible/Games/Snake_Base/Models/Data/SnakeTiles.cs
@@ -0,0 +1,95 @@
+// ***********************************************************************
+// Assembly : Snake_Base
+// Author : Mir
+// Created : 08-26-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+///
+/// The ViewModel namespace.
+///
+///
+namespace Snake_Base.Models.Data
+{
+ ///
+ /// Enum SnakeTiles
+ ///
+ public enum SnakeTiles
+ {
+ ///
+ /// The empty field
+ ///
+ Empty, //0
+ ///
+ /// The wall
+ ///
+ Wall, //1
+ ///
+ /// The apple
+ ///
+ Apple, //2
+ ///
+ /// The snake head north
+ ///
+ SnakeHead_N,//3
+ ///
+ /// The snake tail north
+ ///
+ SnakeTail_N,//4
+ ///
+ /// The snake body north-south
+ ///
+ SnakeBody_NS,//5
+ ///
+ /// The snake head west
+ ///
+ SnakeHead_W,
+ ///
+ /// The snake head south
+ ///
+ SnakeHead_S,
+ ///
+ /// The snake head east
+ ///
+ SnakeHead_E,
+ ///
+ /// The snake tail west
+ ///
+ SnakeTail_W,
+ ///
+ /// The snake tail south
+ ///
+ SnakeTail_S,
+ ///
+ /// The snake tail east
+ ///
+ SnakeTail_E,
+ ///
+ /// The snake body north-west
+ ///
+ SnakeBody_NW,
+ ///
+ /// The snake body south-west
+ ///
+ SnakeBody_SW,
+ ///
+ /// The snake body south-east
+ ///
+ SnakeBody_SE,
+ ///
+ /// The snake body north-east
+ ///
+ SnakeBody_NE,
+ ///
+ /// The snake body west-east
+ ///
+ SnakeBody_WE,
+ };
+
+}
diff --git a/CSharpBible/Games/Snake_Base/Models/Direction.cs b/CSharpBible/Games/Snake_Base/Models/Direction.cs
new file mode 100644
index 000000000..93240d5a4
--- /dev/null
+++ b/CSharpBible/Games/Snake_Base/Models/Direction.cs
@@ -0,0 +1,76 @@
+// ***********************************************************************
+// Assembly : Snake_Base
+// Author : Mir
+// Created : 08-25-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using System.Drawing;
+
+///
+/// The Models namespace.
+///
+///
+namespace Snake_Base.Models
+{
+ ///
+ /// Enum Direction
+ ///
+ public enum Direction
+ {
+ ///
+ /// The north
+ ///
+ North,
+ ///
+ /// The west
+ ///
+ West,
+ ///
+ /// The south
+ ///
+ South,
+ ///
+ /// The east
+ ///
+ East
+ }
+
+ ///
+ /// Class Offsets.
+ ///
+ public static class Offsets
+ {
+ ///
+ /// The dir offsets
+ ///
+ ///
+ static Point[] DirOffsets = { new Point(0, -1), new Point(-1, 0), new Point(0, 1), new Point(1, 0) };
+ ///
+ /// Dirs the offset.
+ ///
+ /// The d.
+ /// Point.
+ public static Point DirOffset(Direction d) => DirOffsets[(int)d];
+
+ ///
+ /// Dirs the offset.
+ ///
+ /// The dir.
+ /// The position.
+ /// Point.
+ public static Point DirOffset(Direction? dir, Point position)
+ {
+ var p = new Point(position.X,position.Y);
+ if (dir.HasValue)
+ p.Offset(DirOffset((Direction)dir));
+ return p;
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGame.cs b/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGame.cs
new file mode 100644
index 000000000..38c615b67
--- /dev/null
+++ b/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGame.cs
@@ -0,0 +1,41 @@
+// ***********************************************************************
+// Assembly : Snake_Base
+// Author : Mir
+// Created : 08-25-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using Game_Base.Model;
+using Snake_Base.Models.Data;
+using System;
+using System.Drawing;
+
+namespace Snake_Base.Models.Interfaces;
+
+public interface ISnakeGame
+{
+ IPlayfield2D Playfield { get; }
+ int Level { get; }
+ bool IsRunning { get; }
+ int Score { get; }
+ int Lives { get; }
+ int MaxLives { get; }
+ Size size { get; }
+ bool UserQuit { set; }
+
+ SnakeTiles this[Point p] { get; }
+
+ event EventHandler? visUpdate;
+ event EventHandler? visFullRedraw;
+
+ Point GetOldPos(Point p);
+ void SetSnakeDir(Direction action);
+ int GameStep();
+ void Setup(int v);
+}
\ No newline at end of file
diff --git a/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGameObject.cs b/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGameObject.cs
new file mode 100644
index 000000000..ecca3b703
--- /dev/null
+++ b/CSharpBible/Games/Snake_Base/Models/Interfaces/ISnakeGameObject.cs
@@ -0,0 +1,23 @@
+// ***********************************************************************
+// Assembly : Snake_Base
+// Author : Mir
+// Created : 08-25-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using System.Drawing;
+
+namespace Snake_Base.Models.Interfaces;
+
+public interface ISnakeGameObject
+{
+ Point OldPlace { get; }
+
+ void ResetOldPlace();
+}
\ No newline at end of file
diff --git a/CSharpBible/Games/Snake_Base/Models/Snake.cs b/CSharpBible/Games/Snake_Base/Models/Snake.cs
new file mode 100644
index 000000000..ef2843503
--- /dev/null
+++ b/CSharpBible/Games/Snake_Base/Models/Snake.cs
@@ -0,0 +1,263 @@
+// ***********************************************************************
+// Assembly : Snake_Base
+// Author : Mir
+// Created : 08-25-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using BaseLib.Model;
+using BaseLib.Helper;
+using BaseLib.Interfaces;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Runtime.CompilerServices;
+using Snake_Base.Models.Interfaces;
+using Game_Base.Model;
+
+///
+/// The Models namespace.
+///
+///
+namespace Snake_Base.Models
+{
+ ///
+ /// Class SnakeBodyPart.
+ /// Implements the
+ /// Implements the
+ ///
+ ///
+ ///
+ public class SnakeBodyPart : SnakeGameObject, IParentedObject
+ {
+ #region Properties
+ #region private Properties
+ ///
+ /// The sn parent
+ ///
+ ///
+ private Snake? _snParent;
+ #endregion
+ ///
+ /// Gets or sets the snake.
+ ///
+ /// The snake.
+ public Snake? Snake { get => _snParent; set => SetParent(value); }
+ ///
+ /// Sets the parent.
+ ///
+ /// The value.
+ /// The caller member.
+ public void SetParent(Snake? value, [CallerMemberName] string CallerMember = "") => value.SetProperty(ref _snParent, null, CallerMember);
+
+ ///
+ /// Gets or sets the next part.
+ ///
+ /// The next part.
+ public SnakeBodyPart? NextPart { get; set; } = null;
+
+ ///
+ /// Gets or sets the previous part.
+ ///
+ /// The next part.
+ public SnakeBodyPart? PrevPart { get; set; }= null;
+ #endregion
+
+ #region Methods
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SnakeBodyPart() : this(null) { }
+
+ ///
+ /// Gets the parent.
+ ///
+ /// System.Nullable<Snake>.
+ ///
+ Snake? IParentedObject.GetParent() => _snParent;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The snake.
+ public SnakeBodyPart(Snake? snake):base()
+ {
+ _snParent = snake;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The place.
+ /// The snake.
+ /// The playfield.
+ public SnakeBodyPart(Point place,Snake? snake, IPlayfield2D? playfield = null) :base(place,playfield)
+ {
+ _snParent = snake;
+ }
+ #endregion
+ }
+
+ ///
+ /// Class SnakeHead.
+ /// Implements the
+ ///
+ ///
+ public class SnakeHead : SnakeBodyPart
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The snake.
+ public SnakeHead(Snake? snake = null) : base(snake) { }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The place.
+ /// The snake.
+ /// The playfield.
+ public SnakeHead(Point place, Snake? snake, IPlayfield2D? playfield = null):base(place,snake,playfield) { }
+ }
+
+ ///
+ /// Class SnakeTail.
+ /// Implements the
+ ///
+ ///
+ public class SnakeTail : SnakeBodyPart
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The snake.
+ public SnakeTail(Snake? snake = null) : base(snake) { }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The place.
+ /// The snake.
+ /// The playfield.
+ public SnakeTail(Point place, Snake? snake, IPlayfield2D? playfield = null) : base(place, snake, playfield) { }
+ }
+
+ ///
+ /// Class Snake.
+ ///
+ public class Snake : NotificationObjectAdv
+ {
+ #region Properties
+ #region private Properties
+ ///
+ /// The playfield
+ ///
+ ///
+ private IPlayfield2D? _playfield;
+ ///
+ /// The sn head
+ ///
+ ///
+ private SnakeHead _snHead;
+ ///
+ /// The sn body
+ ///
+ ///
+ private List _snBody = new List();
+ ///
+ /// The sn tail
+ ///
+ ///
+ private SnakeTail _snTail;
+ ///
+ /// The sn length
+ ///
+ ///
+ private int _snLength;
+ #endregion
+ ///
+ /// The alive
+ ///
+ public bool alive;
+
+ ///
+ /// Gets the length.
+ ///
+ /// The length.
+ public int Length { get => _snLength; private set => SetProperty(ref _snLength,value); }
+ ///
+ /// Gets the head position.
+ ///
+ /// The head position.
+ public Point HeadPos { get => _snHead.Place; }
+
+ public event EventHandler OnSnakeEatsApple;
+ #endregion
+
+ #region Methods
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The start.
+ /// The playfield.
+ public Snake(Point start, IPlayfield2D? playfield=null) {
+ playfield ??= SnakeGameObject.DefaultParent;
+ _playfield = playfield;
+ _snTail = new SnakeTail(start,this);
+ _snHead = new SnakeHead(start,this);
+ _snHead.NextPart = _snTail;
+ _snTail.PrevPart = _snHead;
+ Length = 2; // Head & Tail;
+ alive = true;
+ }
+
+ ///
+ /// Snakes the move.
+ ///
+ /// The dir.
+ public void SnakeMove(Direction dir)
+ {
+ var nextPlace = Offsets.DirOffset(dir, _snHead.Place);
+ if (!_playfield?.Rect.Contains(nextPlace) ?? false) { alive = false;return; }
+ if (_playfield?[nextPlace] is SnakeBodyPart) { alive = false; return; }
+ if (_playfield?[nextPlace] is Apple) {
+ OnSnakeEatsApple?.Invoke(this, new EventArgs());
+ _playfield[nextPlace] = null;
+ Length++;
+ }
+ SnakeBodyPart? _mRun = _snHead;
+ var _nxtPlace = nextPlace;
+ var bCount = 1;
+ while ((_mRun != null) && (_mRun.NextPart != _snTail))
+ {
+ (_mRun.Place, _nxtPlace) = (_nxtPlace, _mRun.Place);
+ if (bCount==1)
+ RaisePropertyChangedAdv(_mRun.OldPlace, _mRun.Place, nameof(HeadPos));
+ _mRun = _mRun.NextPart;
+ bCount++;
+ }
+ if (bCount++ < _snLength && _mRun != null) {
+ (_mRun.Place, _nxtPlace) = (_nxtPlace, _mRun.Place);
+ if (bCount == 2)
+ RaisePropertyChangedAdv(_mRun.OldPlace, _mRun.Place, nameof(HeadPos));
+ var _snBody = new SnakeBodyPart(_nxtPlace,this,_playfield);
+ _snBody.ResetOldPlace();
+ _snBody.NextPart = _mRun.NextPart;
+ _snBody.PrevPart = _mRun;
+ _mRun.NextPart!.PrevPart = _snBody;
+ _mRun.NextPart= _snBody;
+ }
+ else if (_mRun != null)
+ {
+ (_mRun.Place, _nxtPlace) = (_nxtPlace, _mRun.Place);
+ if (bCount == 2)
+ RaisePropertyChangedAdv(_mRun.OldPlace, _mRun.Place, nameof(HeadPos));
+ _snTail.Place = _nxtPlace;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/CSharpBible/Games/Snake_Base/Models/SnakeGame.cs b/CSharpBible/Games/Snake_Base/Models/SnakeGame.cs
new file mode 100644
index 000000000..1bd40bda9
--- /dev/null
+++ b/CSharpBible/Games/Snake_Base/Models/SnakeGame.cs
@@ -0,0 +1,225 @@
+// ***********************************************************************
+// Assembly : Snake_Base
+// Author : Mir
+// Created : 08-25-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using BaseLib.Interfaces;
+using Game_Base.Model;
+using Snake_Base.Models.Data;
+using Snake_Base.Models.Interfaces;
+using System;
+using System.Drawing;
+
+///
+/// The ViewModel namespace.
+///
+///
+namespace Snake_Base.Models
+{
+ ///
+ /// Class SnakeGame.
+ ///
+ public class SnakeGame: ISnakeGame
+ {
+ #region Properties
+ #region private Properties
+ ///
+ /// The random
+ ///
+ ///
+ private static IRandom? _rnd;
+
+ private Direction sDir;
+ private bool _userQuit = false;
+ private bool xHalfStep;
+
+ #endregion
+ ///
+ /// Gets or sets the playfield.
+ ///
+ /// The playfield.
+ public IPlayfield2D Playfield { get; }
+ ///
+ /// Gets or sets the snake.
+ ///
+ /// The snake.
+ public Snake Snake { get; set; }
+ ///
+ /// The get next random
+ ///
+ public int Level { get; }
+ public event EventHandler? visUpdate;
+ public event EventHandler? visFullRedraw;
+ public static readonly int MaxLives;
+
+ ///
+ /// Gets the with the specified p.
+ ///
+ /// The p.
+ /// SnakeTiles.
+ public SnakeTiles this[Point p] => GetTile(p);
+
+ ///
+ /// Gets a value indicating whether this instance is running.
+ ///
+ /// true if this instance is running; otherwise, false.
+ public bool IsRunning => Snake.alive && !_userQuit;
+
+ public int Score { get; private set; }
+ public int Lives { get; private set; }
+ public Size size { get => new Size(Playfield.PfSize.Width+2,Playfield.PfSize.Height+2); }
+
+ int ISnakeGame.MaxLives => MaxLives;
+
+ public bool UserQuit { set => _userQuit=value; }
+ #endregion
+
+ #region Methods
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SnakeGame(IRandom random, IPlayfield2D playfield2D)
+ {
+ _rnd = random;
+ Playfield = playfield2D;
+ Playfield.PfSize = new Size(20, 20);
+ Playfield.OnDataChanged += PfDataChange;
+ SnakeGameObject.DefaultParent = Playfield;
+ Snake = new Snake(new Point(10,10));
+ Snake.OnSnakeEatsApple += OnSnakeEatsApple;
+ }
+
+ private void OnSnakeEatsApple(object? sender, EventArgs e)
+ {
+ NewApple();
+ }
+
+ private void NewApple()
+ {
+ // Getplace for apple
+ Point p;
+ // Get Random Startplace
+ var w = Playfield.PfSize.Width;
+ var sp = _rnd?.Next(Playfield.PfSize.Height * w)??0;
+ while (Playfield[p=new Point(sp % w,sp / w)]!=null)
+ sp++;
+ //
+ var a=new Apple(p, Playfield);
+ a.ResetOldPlace();
+ }
+
+ ///
+ /// Pfs the data change.
+ ///
+ /// The sender.
+ /// The e.
+ ///
+ ///
+ private void PfDataChange(object? sender, (string prop, object? oldVal, object? newVal) e)
+ {
+ // throw new NotImplementedException();
+ }
+
+ ///
+ /// Games the step.
+ ///
+ /// System.Int32.
+ public int GameStep()
+ {
+ xHalfStep = !xHalfStep;
+ if (xHalfStep)
+ {
+ foreach (var i in Playfield.Items)
+ i.ResetOldPlace();
+ Snake.SnakeMove(sDir);
+ }
+ visUpdate?.Invoke(this, xHalfStep);
+ return 150;
+ }
+
+ ///
+ /// Gets the tile.
+ ///
+ /// The p.
+ /// SnakeTiles.
+ public SnakeTiles GetTile(Point p)
+ {
+ SnakeTiles result = SnakeTiles.Empty;
+ var field = Playfield[p];
+ switch(field)
+ {
+ case Apple:
+ result = SnakeTiles.Apple; break;
+ case SnakeHead sh:
+ {
+ var np = Point.Subtract(sh.Place, (Size?)sh.NextPart?.Place??Size.Empty);
+ switch ((np.X, np.Y))
+ {
+ case (1, 0): result = SnakeTiles.SnakeHead_E; break;
+ case (-1, 0): result = SnakeTiles.SnakeHead_W; break;
+ case (0, 1): result = SnakeTiles.SnakeHead_S; break;
+ case (0, -1): result = SnakeTiles.SnakeHead_N; break;
+ }
+ break;
+ }
+ case SnakeTail st: {
+ var np = Point.Subtract(st.Place, (Size?)st.PrevPart?.Place??Size.Empty);
+ switch ((np.X, np.Y))
+ {
+ case (1, 0): result = SnakeTiles.SnakeTail_W; break;
+ case (-1, 0): result = SnakeTiles.SnakeTail_E; break;
+ case (0, 1): result = SnakeTiles.SnakeTail_N; break;
+ case (0, -1): result = SnakeTiles.SnakeTail_S; break;
+ }
+ break; }
+ case SnakeBodyPart sb: {
+ var nx = Point.Subtract(sb.Place, (Size?)sb.NextPart?.Place ?? Size.Empty);
+ var np = Point.Subtract(sb.Place, (Size?)sb.PrevPart?.Place ?? Size.Empty);
+ switch ((np.X+nx.X, np.Y+nx.Y))
+ {
+ case (0, 0) when nx.Y==0: result = SnakeTiles.SnakeBody_WE; break;
+ case (0, 0) when nx.X == 0: result = SnakeTiles.SnakeBody_NS; break;
+ case (1, 1): result = SnakeTiles.SnakeBody_NE; break;
+ case (-1, 1): result = SnakeTiles.SnakeBody_NW; break;
+ case (-1, -1): result = SnakeTiles.SnakeBody_SW; break;
+ case (1, -1): result = SnakeTiles.SnakeBody_SE; break;
+ }
+ break;
+ }
+ default:
+ if (Playfield.IsInside(p))
+ result = SnakeTiles.Empty;
+ else
+ result = SnakeTiles.Wall;
+ break;
+ }
+ return result;
+ }
+
+ public Point GetOldPos(Point arg)
+ {
+ return Playfield[arg]?.OldPlace ?? arg;
+ }
+
+ public void Setup(int v)
+ {
+ NewApple();
+ //throw new NotImplementedException();
+ }
+
+ public void SetSnakeDir(Direction action)
+ {
+ sDir = action;
+ }
+
+ #endregion
+ }
+}
diff --git a/CSharpBible/Games/Snake_Base/Models/SnakeGameObject.cs b/CSharpBible/Games/Snake_Base/Models/SnakeGameObject.cs
new file mode 100644
index 000000000..978d73677
--- /dev/null
+++ b/CSharpBible/Games/Snake_Base/Models/SnakeGameObject.cs
@@ -0,0 +1,183 @@
+// ***********************************************************************
+// Assembly : Snake_Base
+// Author : Mir
+// Created : 08-25-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using BaseLib.Helper;
+using BaseLib.Interfaces;
+using Game_Base.Model;
+using Game_Base.Model.Interfaces;
+using Snake_Base.Models.Interfaces;
+using System;
+using System.Drawing;
+using System.Runtime.CompilerServices;
+
+///
+/// The Models namespace.
+///
+///
+namespace Snake_Base.Models
+{
+ ///
+ /// Class SnakeGameObject.
+ /// Implements the
+ /// Implements the
+ ///
+ ///
+ ///
+ public abstract class SnakeGameObject :ISnakeGameObject, IPlacedObject, IParentedObject>
+ {
+ #region Properties
+ #region private Properties
+ ///
+ /// The place
+ ///
+ ///
+ private Point _place=Point.Empty;
+ ///
+ /// The old place
+ ///
+ ///
+ private Point _oldPlace;
+ ///
+ /// The pf parent
+ ///
+ ///
+ private IPlayfield2D? _pfParent;
+ #endregion
+ #region static Properties
+ ///
+ /// Gets or sets the default parent.
+ ///
+ /// The default parent.
+ public static IPlayfield2D? DefaultParent { get; set; } = null;
+ #endregion
+
+ ///
+ /// Occurs when [data change event].
+ ///
+ public event EventHandler<(string sender, object? oldVal, object? newVal)>? DataChangeEvent;
+ ///
+ /// Occurs when [on place change].
+ ///
+ public event EventHandler<(Point oP, Point nP)>? OnPlaceChange;
+
+ ///
+ /// Gets the old place.
+ ///
+ /// The old place.
+ public Point OldPlace { get => GetOldPlace(); }
+ #region interface Properties
+ ///
+ /// Gets or sets the place.
+ ///
+ /// The place.
+ public Point Place { get => GetPlace();set=> SetPlace(value); }
+ ///
+ /// Gets or sets the parent.
+ ///
+ /// The parent.
+ public IPlayfield2D? Parent { get => GetParent(); set => SetParent(value); }
+ #endregion
+ #endregion
+
+ #region Methods
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SnakeGameObject() : this(Point.Empty) { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The place.
+ /// The parent.
+ public SnakeGameObject(Point place, IPlayfield2D? parent=null) {
+ Place= place;
+ if (parent!=null)
+ Parent = parent;
+ else if (DefaultParent!=null)
+ Parent= DefaultParent;
+ }
+
+ #region interface Methods
+ ///
+ /// Gets the old place.
+ ///
+ /// Point.
+ public virtual Point GetOldPlace() => _oldPlace;
+ ///
+ /// Gets the place.
+ ///
+ /// Point.
+ public virtual Point GetPlace() => _place;
+ ///
+ /// Sets the place.
+ ///
+ /// The value.
+ /// The name.
+ public virtual void SetPlace(Point value, [CallerMemberName] string Name = "") => value.SetProperty(ref _place, NtfyPlaceChange, Name);
+
+ ///
+ /// Gets the parent.
+ ///
+ /// System.Nullable<Playfield2D<SnakeGameObject>>.
+ public virtual IPlayfield2D? GetParent() => _pfParent;
+ ///
+ /// Sets the parent.
+ ///
+ /// The value.
+ /// The caller member.
+ public virtual void SetParent(IPlayfield2D? value, [CallerMemberName] string CallerMember = "") =>
+ value.SetProperty(ref _pfParent, NtfyParentChange, CallerMember);
+ #endregion
+
+ ///
+ /// Ntfies the parent change.
+ ///
+ /// The arg1.
+ /// The arg2.
+ /// The arg3.
+ ///
+ protected virtual void NtfyParentChange(string arg1, IPlayfield2D? arg2, IPlayfield2D? arg3)
+ {
+ if (arg2 is IHasChildren hc)
+ hc.RemoveItem(this);
+ if (arg3 is IHasChildren hc2)
+ hc2.AddItem(this);
+ if (arg3 is IHasChildren hc3)
+ hc3.AddItem(this);
+ DataChangeEvent?.Invoke(this, (arg1, arg2, arg3));
+ }
+
+ ///
+ /// Ntfies the place change.
+ ///
+ /// The arg1.
+ /// The arg2.
+ /// The arg3.
+ ///
+ protected virtual void NtfyPlaceChange(string arg1, Point arg2, Point arg3)
+ {
+ _oldPlace = arg2;
+ if (_pfParent is IHasChildren hc)
+ hc.NotifyChildChange(this, arg2, arg3);
+ OnPlaceChange?.Invoke(this, (arg2, arg3));
+ DataChangeEvent?.Invoke(this, (arg1, arg2, arg3));
+ }
+
+ public void ResetOldPlace()
+ {
+ _oldPlace = _place;
+ }
+ #endregion
+ }
+}
diff --git a/CSharpBible/Games/Snake_Base/ViewModels/ISnakeViewModel.cs b/CSharpBible/Games/Snake_Base/ViewModels/ISnakeViewModel.cs
new file mode 100644
index 000000000..c3883003d
--- /dev/null
+++ b/CSharpBible/Games/Snake_Base/ViewModels/ISnakeViewModel.cs
@@ -0,0 +1,38 @@
+// ***********************************************************************
+// Assembly : Snake_Console
+// Author : Mir
+// Created : 08-02-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using Snake_Base.Models.Data;
+using System;
+using System.ComponentModel;
+using System.Drawing;
+
+namespace Snake_Base.ViewModels;
+
+public interface ISnakeViewModel: INotifyPropertyChanged
+{
+ public interface ITileProxy
+ {
+ public T this[Point p] { get; }
+ }
+
+ UserAction UserAction { get; set; }
+ ITileProxy Tiles { get; }
+
+ Func GetOldPos { get; }
+ Size size { get; }
+ int Level { get; }
+ int Score { get; }
+ int Lives { get; }
+ int MaxLives { get; }
+ bool HalfStep { get; }
+}
\ No newline at end of file
diff --git a/CSharpBible/Games/Snake_Base/ViewModels/SnakeViewModel.cs b/CSharpBible/Games/Snake_Base/ViewModels/SnakeViewModel.cs
new file mode 100644
index 000000000..13a267874
--- /dev/null
+++ b/CSharpBible/Games/Snake_Base/ViewModels/SnakeViewModel.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using BaseLib.Helper;
+using CommunityToolkit.Mvvm.ComponentModel;
+using Snake_Base.Models;
+using Snake_Base.Models.Data;
+using Snake_Base.Models.Interfaces;
+
+namespace Snake_Base.ViewModels;
+
+public partial class SnakeViewModel : ObservableObject, ISnakeViewModel
+{
+ ISnakeGame _game;
+
+ [ObservableProperty]
+ private UserAction _userAction;
+ private bool _halfStep;
+
+ public SnakeViewModel(ISnakeGame game)
+ {
+ _game = game;
+ Tiles = new _TileProxy(game);
+ _game.visUpdate += (s, e) =>
+ {
+ _halfStep = e;
+ OnPropertyChanged(nameof(Tiles));
+ };
+ _game.visFullRedraw += (s, e) => OnPropertyChanged(nameof(Level));
+ }
+
+ public class _TileProxy(ISnakeGame game) : ISnakeViewModel.ITileProxy
+ {
+ ISnakeGame _game = game;
+ public SnakeTiles this[Point p]
+ { get => _game[p]; }
+ }
+
+ public ISnakeViewModel.ITileProxy Tiles { get; }
+
+ public Size size => _game.size;
+ public int Level => _game.Level;
+ public int Score => _game.Score;
+ public int Lives => _game.Lives;
+ public int MaxLives => _game.MaxLives;
+
+ public Func GetOldPos { get => _game.GetOldPos; }
+
+ public bool HalfStep => _halfStep;
+
+ partial void OnUserActionChanged(UserAction value)
+ {
+ if ((int)value < typeof(Direction).GetEnumValues().Length)
+ _game.SetSnakeDir((Direction)value);
+ else if (value <= UserAction.Quit)
+ _game.UserQuit = true;
+ }
+
+}
diff --git a/CSharpBible/Games/Snake_Console/Program.cs b/CSharpBible/Games/Snake_Console/Program.cs
index 877419a57..e22f3b881 100644
--- a/CSharpBible/Games/Snake_Console/Program.cs
+++ b/CSharpBible/Games/Snake_Console/Program.cs
@@ -9,15 +9,17 @@
using Snake_Console.View;
using System;
using System.Threading;
+using Game_Base.Model;
namespace Snake_Console
{
public static class Program
{
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fgen Sie ggf. den erforderlichen Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend.
private static ISnakeGame _game;
- private static UserAction action;
- private static int iDelay;
private static IVisual _visual;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fgen Sie ggf. den erforderlichen Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend.
+ private static int iDelay;
private static void OnStartUp()
{
@@ -25,8 +27,10 @@ private static void OnStartUp()
.AddTransient()
.AddTransient()
.AddSingleton()
+ .AddSingleton, Playfield2D>()
.AddSingleton()
- .AddSingleton, TileDisplay>()
+ .AddTransient, TileDisplay>()
+ .AddTransient()
.AddSingleton();
var sp = sc.BuildServiceProvider();
diff --git a/CSharpBible/Games/Snake_Console/Snake_Console_net.csproj b/CSharpBible/Games/Snake_Console/Snake_Console_net.csproj
index f953daa23..90acc3fee 100644
--- a/CSharpBible/Games/Snake_Console/Snake_Console_net.csproj
+++ b/CSharpBible/Games/Snake_Console/Snake_Console_net.csproj
@@ -1,4 +1,4 @@
-
+
Exe
@@ -8,6 +8,8 @@
+
+
diff --git a/CSharpBible/Games/Snake_Console/View/IVisual.cs b/CSharpBible/Games/Snake_Console/View/IVisual.cs
new file mode 100644
index 000000000..7b125d82b
--- /dev/null
+++ b/CSharpBible/Games/Snake_Console/View/IVisual.cs
@@ -0,0 +1,23 @@
+// ***********************************************************************
+// Assembly : Snake_Console
+// Author : Mir
+// Created : 08-02-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 09-09-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using System;
+
+namespace Snake_Console.View
+{
+ public interface IVisual
+ {
+ bool CheckUserAction();
+ void FullRedraw(object? sender = null, EventArgs? e = null);
+ }
+}
\ No newline at end of file
diff --git a/CSharpBible/Games/Snake_Console/View/TileDef.cs b/CSharpBible/Games/Snake_Console/View/TileDef.cs
index 19cfc19d8..b6dded0b7 100644
--- a/CSharpBible/Games/Snake_Console/View/TileDef.cs
+++ b/CSharpBible/Games/Snake_Console/View/TileDef.cs
@@ -11,83 +11,82 @@
//
//
// ***********************************************************************
-using ConsoleDisplay.View;
using System;
+using ConsoleDisplay.View;
using System.Drawing;
///
/// The View namespace.
///
///
-namespace Snake_Console.View
+namespace Snake_Console.View;
+
+///
+/// Class TileDef.
+/// Implements the
+///
+public class TileDef : TileDefBase
{
///
- /// Class TileDef.
- /// Implements the
- ///
- public class TileDef : TileDefBase
- {
- ///
- /// The v tile definition string
- ///
- ///
- private static string[][] _vTileDefStr = new string[][]{
- new string[]{ " " }, //Empty
- new string[]{ "|_" }, //Wall
- new string[]{ "##" }, //Apple
- new string[]{ "/\\" }, //Head_N
- new string[]{ "''" }, //Tail_N
- new string[]{ "||" }, //Boby_NS
- new string[]{ "<}" }, //Head_W
- new string[]{ "\\/" }, //Head_S
- new string[]{ "{>" }, //Head_E
- new string[]{ "=-" }, //Tail_W
- new string[]{ ",," }, //Tail_S
- new string[]{ "-=" }, //Tail_E
- new string[]{ "++" },
- new string[]{ "++" },
- new string[]{ "++" },
- new string[]{ "++" },
- new string[]{ "==" }, //Body_WE
- };
+ /// The v tile definition string
+ ///
+ ///
+ private string[][] _vTileDefStr = [
+ [" "], //Empty
+ ["|_"], //Wall
+ ["##"], //Apple
+ ["/\\"], //Head_N
+ ["''"], //Tail_N
+ ["||"], //Boby_NS
+ ["<}"], //Head_W
+ ["\\/"], //Head_S
+ ["{>"], //Head_E
+ ["=-"], //Tail_W
+ [",,"], //Tail_S
+ ["-="], //Tail_E
+ ["++"],
+ ["++"],
+ ["++"],
+ ["++"],
+ ["=="], //Body_WE
+ ];
- ///
- /// The v tile colors
- ///
- ///
- private static byte[][] _vTileColors = new byte[][]{
- new byte [] { 0x07 }, //Empty
- new byte [] { 0x4F }, //Wall
- new byte [] { 0x0C }, //Apple
- new byte [] { 0xAE }, //Head_N
- new byte [] { 0x0E },
- new byte [] { 0x0E },
- new byte [] { 0xAE },
- new byte [] { 0xAE },
- new byte [] { 0xAE },
- new byte [] { 0x0E } //Rest ...
- };
+ ///
+ /// The v tile colors
+ ///
+ ///
+ private byte[][] _vTileColors = [
+ [0x07], //Empty
+ [0x4F], //Wall
+ [0x0C], //Apple
+ [0xAE], //Head_N
+ [0x0E],
+ [0x0E],
+ [0xAE],
+ [0xAE],
+ [0xAE],
+ [0x0E] //Rest ...
+ ];
- ///
- /// Gets the tile definition.
- ///
- /// The tile.
- /// (string[] lines, (System.ConsoleColor fgr, System.ConsoleColor bgr)[] colors).
- ///
- public override (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum tile)
- {
- (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) result = default;
- result.lines = GetArrayElement(_vTileDefStr, tile);
+ ///
+ /// Gets the tile definition.
+ ///
+ /// The tile.
+ /// (string[] lines, (System.ConsoleColor fgr, System.ConsoleColor bgr)[] colors).
+ ///
+ public override (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile)
+ {
+ (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) result = default;
+ result.lines = GetArrayElement(_vTileDefStr, tile);
- result.colors = new (ConsoleColor fgr, ConsoleColor bgr)[result.lines.Length * result.lines[0].Length];
- byte[] colDef = GetArrayElement(_vTileColors, tile);
- for (var i = 0; i < result.lines.Length * result.lines[0].Length; i++)
- result.colors[i] = ByteTo2ConsColor(colDef[i % colDef.Length]);
- return result;
- }
+ result.colors = new (ConsoleColor fgr, ConsoleColor bgr)[result.lines.Length * result.lines[0].Length];
+ byte[] colDef = GetArrayElement(_vTileColors, tile);
+ for (var i = 0; i < result.lines.Length * result.lines[0].Length; i++)
+ result.colors[i] = ByteTo2ConsColor(colDef[i % colDef.Length]);
+ return result;
+ }
- public TileDef():base() {
- TileSize = new Size(2, 1);
- }
+ public TileDef():base() {
+ TileSize = new Size(2, 1);
}
}
diff --git a/CSharpBible/Games/Snake_Console/View/Visual.cs b/CSharpBible/Games/Snake_Console/View/Visual.cs
index 7259174ed..072fdebcf 100644
--- a/CSharpBible/Games/Snake_Console/View/Visual.cs
+++ b/CSharpBible/Games/Snake_Console/View/Visual.cs
@@ -17,6 +17,7 @@
using System.Drawing;
using Snake_Base.ViewModels;
using System.ComponentModel;
+using Snake_Base.Models.Data;
namespace Snake_Console.View
{
@@ -29,14 +30,14 @@ public class Visual : IVisual {
/// The game
///
- private ISnakeViewModel? _game;
+ private ISnakeViewModel _viewModel;
///
/// My console
///
public IConsole myConsole;
- private ITileDisplay _tileDisplay;
+ private ITileDisplay _tileDisplay;
///
/// The key action
///
@@ -55,45 +56,37 @@ public class Visual : IVisual {
#endregion
#region Methods
- public Visual(ISnakeViewModel viewModel, ITileDisplay tileDisplay)
+ public Visual(ISnakeViewModel viewModel, ITileDisplay tileDisplay)
{
+ _viewModel = viewModel;
+ _viewModel.PropertyChanged += OnPropertyChanged;
+
myConsole = tileDisplay.console;
_tileDisplay = tileDisplay;
_tileDisplay.DispOffset = new Point(-1, -1);
- _tileDisplay.FncGetTile = (p) => (Enum)_game.Tiles[(Point)p];
- _tileDisplay.FncOldPos = _game.GetOldPos;
+ _tileDisplay.SetDispSize ( new Size(22, 22));
+ _tileDisplay.FncGetTile = (p) => _viewModel.Tiles[(Point)p];
+ _tileDisplay.FncOldPos = _viewModel.GetOldPos;
- _game = viewModel;
- _game.PropertyChanged += OnPropertyChanged;
FullRedraw();
}
- private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
- if (e.PropertyName == nameof(_game.Tiles))
+ if (e.PropertyName == nameof(_viewModel.Tiles))
{
- _tileDisplay.Update(_game.HalfStep);
+ _tileDisplay.Update(_viewModel.HalfStep);
ShowStatistics();
}
- else if (e.PropertyName == nameof(_game.Level))
+ else if (e.PropertyName == nameof(_viewModel.Level))
{
FullRedraw();
}
}
-
- ///
- /// gs the vis update.
- ///
- /// The sender.
- /// if set to true [e].
- private static void G_visUpdate(object? sender, bool e)
- {
- }
-
///
/// Fulls the redraw.
///
@@ -102,7 +95,7 @@ private static void G_visUpdate(object? sender, bool e)
public void FullRedraw(object? sender=null,EventArgs? e=null)
{
// basic Checks
- if (_game == null) return;
+ if (_viewModel == null) return;
_tileDisplay.FullRedraw();
// Draw statistics
@@ -114,11 +107,11 @@ public void FullRedraw(object? sender=null,EventArgs? e=null)
///
private void ShowStatistics()
{
- if (_game == null) return;
+ if (_viewModel == null) return;
myConsole.SetCursorPosition(0, 24);
myConsole.BackgroundColor = ConsoleColor.Black;
myConsole.ForegroundColor = ConsoleColor.Yellow;
- myConsole.Write($"\t{_game.Level + 1}\t\t{_game.Score}\t\t{_game.Lives}/{_game.MaxLives}\t\x08");
+ myConsole.Write($"\t{_viewModel.Level + 1}\t\t{_viewModel.Score}\t\t{_viewModel.Lives}/{_viewModel.MaxLives}\t\x08");
}
@@ -163,8 +156,8 @@ public bool CheckUserAction()
result = true;
}
}
- if (_game != null)
- _game.UserAction = action;
+ if (_viewModel != null)
+ _viewModel.UserAction = action;
return result;
}
diff --git a/CSharpBible/Games/Sokoban_Base/View/Visuals.cs b/CSharpBible/Games/Sokoban_Base/View/Visuals.cs
index 9aceb09fb..f2b39c952 100644
--- a/CSharpBible/Games/Sokoban_Base/View/Visuals.cs
+++ b/CSharpBible/Games/Sokoban_Base/View/Visuals.cs
@@ -53,6 +53,8 @@ public static class Visuals
{ 'Q', UserAction.Quit },
{ '\u001b', UserAction.Quit } };
+ private static ITileDef _visualDef;
+
///
/// Gets or sets the message.
///
@@ -72,6 +74,8 @@ static Visuals()
KeyAction.Add(dir.ToString()?[0] ?? '\0', (UserAction)dir);
}
catch { }
+
+ _visualDef = new VisualsDef();
}
///
@@ -200,13 +204,13 @@ private static void ShowHelp()
var sDirs = "";
foreach (string d in typeof(Direction).GetEnumNames()) sDirs += $", {MarkFirst(d)}";
- myConsole.WriteLine(String.Format(Resource1.InfoText,
+ myConsole.WriteLine(string.Format(Resource1.InfoText,
Resource1.stone,
sDirs.TrimStart(','),
- $"{VisualsDef.GetTileStr(TileDef.Stone)[0]}\r\n{VisualsDef.GetTileStr(TileDef.Stone)[1]}",
- $"{VisualsDef.GetTileStr(TileDef.Player)[0]}\r\n{VisualsDef.GetTileStr(TileDef.Player)[1]}",
- $"{VisualsDef.GetTileStr(TileDef.Wall)[0]}\r\n{VisualsDef.GetTileStr(TileDef.Wall)[1]}",
- $"{VisualsDef.GetTileStr(TileDef.Destination)[0]}\r\n{VisualsDef.GetTileStr(TileDef.Destination)[1]}"
+ $"{_visualDef.GetTileDef(TileDef.Stone).lines[0]}\r\n{_visualDef.GetTileDef(TileDef.Stone).lines[1]}",
+ $"{_visualDef.GetTileDef(TileDef.Player).lines[0]} \r\n {_visualDef.GetTileDef(TileDef.Player).lines[1]}",
+ $"{_visualDef.GetTileDef(TileDef.Wall).lines[0]} \r\n {_visualDef.GetTileDef(TileDef.Wall).lines[1]}",
+ $"{_visualDef.GetTileDef(TileDef.Destination).lines[0]} \r\n {_visualDef.GetTileDef(TileDef.Destination).lines[1]}"
));
var cp = myConsole.GetCursorPosition();
WriteTile(new PointF(0, (cp.Top - 3) * 0.5f), TileDef.Destination);
@@ -269,14 +273,13 @@ private static void ShowStatistics()
#endif
static void WriteTile(PointF p, TileDef td)
{
- var colors = VisualsDef.GetTileColors(td);
- var sTileStr=VisualsDef.GetTileStr(td);
- myConsole.ForegroundColor = colors[0];
- myConsole.BackgroundColor = colors[1];
- for (int i = 0; i < sTileStr.Length; i++)
+ var tld = _visualDef.GetTileDef(td);
+ myConsole.ForegroundColor = tld.colors[0].fgr;
+ myConsole.BackgroundColor = tld.colors[0].bgr;
+ for (int i = 0; i < tld.lines.Length; i++)
{
myConsole.SetCursorPosition((int)(p.X * 4), (int)(p.Y * 2) + i);
- myConsole.Write(sTileStr[i]);
+ myConsole.Write(tld.lines[i]);
}
}
diff --git a/CSharpBible/Games/Sokoban_Base/View/VisualsDef.cs b/CSharpBible/Games/Sokoban_Base/View/VisualsDef.cs
index 415e31cac..5c52b0c6e 100644
--- a/CSharpBible/Games/Sokoban_Base/View/VisualsDef.cs
+++ b/CSharpBible/Games/Sokoban_Base/View/VisualsDef.cs
@@ -11,14 +11,16 @@
//
//
// ***********************************************************************
+using ConsoleDisplay.View;
using Sokoban_Base.ViewModel;
using System;
+using System.Drawing;
namespace Sokoban_Base.View {
///
/// Class VisualsDef.
///
- public static class VisualsDef {
+ public class VisualsDef: ITileDef {
///
/// The g STR1
@@ -42,12 +44,14 @@ public static class VisualsDef {
static string[] pStr1 = { "|()|", @" <°)", "(°°)", @"(°> ",
"(__)", @">-||", "|^^|", @"||-<" };
- ///
- /// Gets the tile string.
- ///
- /// The tile definition.
- /// System.String[].
- public static string[] GetTileStr(TileDef tileDef) {
+ public Size TileSize => new Size(4, 2);
+
+ ///
+ /// Gets the tile string.
+ ///
+ /// The tile definition.
+ /// System.String[].
+ public static string[] GetTileStr(TileDef tileDef) {
String[] result ={ "","" };
if ((int)tileDef < gStr1.Length / 2 && tileDef != TileDef.Player)
(result[0], result[1]) = (gStr1[(int)tileDef], gStr1[(int)tileDef + gStr1.Length / 2]);
@@ -106,21 +110,26 @@ public static string[] GetTileStr(TileDef tileDef) {
///
/// The tile definition.
/// ConsoleColor[].
- public static ConsoleColor[] GetTileColors(TileDef tileDef)
+ public static (ConsoleColor fgr,ConsoleColor bgr) GetTileColors(TileDef tileDef)
{
- ConsoleColor[] result = new ConsoleColor[2] { ConsoleColor.Gray, ConsoleColor.Black };
+ var result = ( ConsoleColor.Gray, ConsoleColor.Black );
if ((int)tileDef < gColors.Length / 2)
- (result[0], result[1]) = (gColors[(int)tileDef], gColors[(int)tileDef + gColors.Length / 2]);
+ result = (gColors[(int)tileDef], gColors[(int)tileDef + gColors.Length / 2]);
else if (tileDef == TileDef.Floor_Marked)
- (result[0], result[1]) = (gColors[(int)TileDef.Floor], gColors[(int)TileDef.Floor + gColors.Length / 2]);
+ result = (gColors[(int)TileDef.Floor], gColors[(int)TileDef.Floor + gColors.Length / 2]);
else if (tileDef >= TileDef.Player_W && tileDef <= TileDef.PlayerOverDest_E)
{
var td = (int)tileDef % 2 + (int)TileDef.Player;
- (result[0], result[1]) = (gColors[td], gColors[td + gColors.Length / 2]);
+ result = (gColors[td], gColors[td + gColors.Length / 2]);
}
else
- (result[0], result[1]) = (gColors[(int)TileDef.Wall], gColors[(int)TileDef.Wall + gColors.Length / 2]);
+ result = (gColors[(int)TileDef.Wall], gColors[(int)TileDef.Wall + gColors.Length / 2]);
return result;
}
- }
+
+ public (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile)
+ {
+ return (GetTileStr((TileDef)tile), [GetTileColors((TileDef)tile)]);
+ }
+ }
}
diff --git a/CSharpBible/Games/VTileEdit/Models/EStreamType.cs b/CSharpBible/Games/VTileEdit/Models/EStreamType.cs
new file mode 100644
index 000000000..2fa72fefb
--- /dev/null
+++ b/CSharpBible/Games/VTileEdit/Models/EStreamType.cs
@@ -0,0 +1,11 @@
+namespace VTileEdit.Models
+{
+ public enum EStreamType
+ {
+ Binary,
+ Text,
+ Json,
+ Code,
+ Xml
+ }
+}
\ No newline at end of file
diff --git a/CSharpBible/Games/VTileEdit/Models/IVTEModel.cs b/CSharpBible/Games/VTileEdit/Models/IVTEModel.cs
new file mode 100644
index 000000000..eda21af00
--- /dev/null
+++ b/CSharpBible/Games/VTileEdit/Models/IVTEModel.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Drawing;
+using System.IO;
+
+namespace VTileEdit.Models;
+
+public interface IVTEModel
+{
+ void LoadFromStream(Stream stream, EStreamType eStreamType);
+ void SaveToStream(Stream stream, EStreamType eStreamType);
+ void Clear();
+ void SetTileSize(Size size);
+ Size TileSize { get; }
+ SingleTile GetTileDef(Enum? tile);
+ void SetTileDef(Enum tile, string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors);
+ }
\ No newline at end of file
diff --git a/CSharpBible/Games/VTileEdit/Models/VisTileData.cs b/CSharpBible/Games/VTileEdit/Models/VisTileData.cs
new file mode 100644
index 000000000..59e47a386
--- /dev/null
+++ b/CSharpBible/Games/VTileEdit/Models/VisTileData.cs
@@ -0,0 +1,443 @@
+using ConsoleDisplay.View;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel.DataAnnotations;
+using System.Data;
+using System.Data.SqlTypes;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.PortableExecutable;
+using System.Text;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Shapes;
+using System.Xml.Serialization;
+
+namespace VTileEdit.Models;
+
+public class VisTileData : ITileDef
+{
+ private Size _size;
+ private Dictionary _storage = new();
+
+ public Size TileSize => _size;
+
+ public static bool EqualTo(IEnumerable a, IEnumerable b)
+ {
+ return a.Zip(b).All((t) => t.First!.Equals(t.Second));
+ }
+
+
+
+ public SingleTile GetTileDef(Enum? tile)
+ {
+ if (_storage.TryGetValue(tile, out var result))
+ {
+ return result;
+ }
+ else
+ if (_storage.TryGetValue(_storage.Keys.FirstOrDefault((t) => (int)(object)t == (int)(object)tile), out result))
+ {
+ return result;
+ }
+ else
+ return (new string[0], new (ConsoleColor fgr, ConsoleColor bgr)[0]);
+ }
+
+
+ public void SetTileDefs(ITileDef tiledef) where T : Enum
+ {
+ Clear();
+ _size = tiledef.TileSize;
+ foreach (T e in Enum.GetValues(typeof(T)))
+ {
+ var tile = tiledef.GetTileDef(e);
+ _storage.Add(e, tile);
+ }
+ for (var i = _storage.Count - 2; i > 0; i--)
+ {
+ var e0 = _storage.ElementAt(i).Value;
+ var e1 = _storage.ElementAt(i + 1).Value;
+ if (e0.lines.Length == e1.lines.Length
+ && EqualTo(e0.lines, e1.lines)
+ && e0.colors.Length == e1.colors.Length
+ && EqualTo(e0.colors.Select((c) => (int)c.fgr + (int)c.bgr * 256), e1.colors.Select((c) => (int)c.fgr + (int)c.bgr * 256)))
+ _storage.Remove(_storage.ElementAt(i + 1).Key);
+ else
+ break;
+ }
+ }
+
+ public bool LoadFromStream(Stream stream, EStreamType eStreamType)
+ {
+ switch (eStreamType)
+ {
+ case EStreamType.Binary:
+ {
+ _storage.Clear();
+ using (BinaryReader reader = new BinaryReader(stream))
+ {
+ Type _keyType = typeof(object);
+ int count = reader.ReadInt32();
+ if (count > 0)
+ {
+ _size = new Size(reader.ReadInt32(), reader.ReadInt32());
+ _keyType = Type.GetType(reader.ReadString()) ?? Assembly.GetExecutingAssembly().GetType();
+ }
+ for (int i = 0; i < count; i++)
+ {
+ Enum key = (Enum)Enum.ToObject(_keyType, reader.ReadInt32());
+ int lineCount = reader.ReadInt32();
+ string[] lines = new string[lineCount];
+ for (int j = 0; j < lineCount; j++)
+ {
+ lines[j] = reader.ReadString();
+ }
+ int colorCount = reader.ReadInt32();
+ FullColor[] colors = new FullColor[colorCount];
+ for (int j = 0; j < colorCount; j++)
+ {
+ colors[j] = ((ConsoleColor)reader.ReadByte(), (ConsoleColor)reader.ReadByte());
+ }
+ _storage.Add(key, new SingleTile(lines, colors));
+ }
+ }
+ return true;
+ }
+ case EStreamType.Text:
+ {
+ int iSplPos;
+ (string key, string Value) kv(string line)
+ => (line.Substring(0, iSplPos = line.IndexOf(':')), line.Substring(iSplPos + 1));
+
+ Dictionary? data = new();
+ using (TextReader reader = new StreamReader(stream))
+ {
+ string? line;
+ while ((line = reader.ReadLine()) != null)
+ {
+ var (key, value) = kv(line);
+ if (key == "Count")
+ {
+ data = new();
+ Type KeyType;
+ int count = int.Parse(value);
+ if (count > 0)
+ {
+ (key, value) = kv(reader.ReadLine() ?? ":");
+ var size = value.Split(',');
+ _size = new Size(int.Parse(size[0]), int.Parse(size[1]));
+ (key, value) = kv(reader.ReadLine() ?? ":");
+ KeyType = Type.GetType(value);
+
+ for (int i = 0; i < count; i++)
+ {
+ (key, value) = kv(reader.ReadLine() ?? ":");
+ var keyE = (Enum)Enum.Parse(KeyType, value.Substring(0, value.IndexOf(' ') - 0));
+ (key, value) = kv(reader.ReadLine() ?? ":");
+ var lineCount = int.Parse(value);
+ string[] lines = new string[lineCount];
+ for (int j = 0; j < lineCount; j++)
+ {
+ (key, value) = kv(reader.ReadLine() ?? ":");
+ lines[j] = value;
+ }
+
+ (key, value) = kv(reader.ReadLine() ?? ":");
+ var colorCount = int.Parse(value);
+ FullColor[] colors = new FullColor[colorCount];
+ for (int j = 0; j < colorCount; j++)
+ {
+ (key, value) = kv(reader.ReadLine() ?? ":");
+ var color = Convert.FromHexString(value.Substring(2));
+ colors[j] = ((ConsoleColor)(color[0] >> 4), (ConsoleColor)(color[0] & 0xf));
+ }
+ data.Add(keyE, new SingleTile(lines, colors));
+
+ }
+ }
+ }
+ }
+ }
+ _storage = data ?? _storage;
+ return data != null;
+ }
+ case EStreamType.Xml:
+ {
+ Dictionary? data = new();
+
+ using (TextReader reader = new StreamReader(stream))
+ {
+ var xml = new XmlSerializer(typeof(List
/// The tile.
/// FullColor[].
- public static FullColor[] GetTileColors(Tiles tile)
+ private (ConsoleColor fgr, ConsoleColor bgr)[] GetTileColors(Tiles? tile)
{
- var result = new FullColor[8];
+ var result = new (ConsoleColor fgr, ConsoleColor bgr)[8];
byte[] colDef;
- if ((int)tile < _vTileColors.Length)
+ if ((int?)tile < _vTileColors.Length)
colDef = _vTileColors[(int)tile];
else
colDef = _vTileColors[_vTileColors.Length - 1];
for (var i =0;i> 4));
}
return result;
}
- }
+ public (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile)
+ => (GetTileStr((Tiles?)tile), GetTileColors((Tiles?)tile));
+ }
}
diff --git a/CSharpBible/Games/Werner_Flaschbier/View/Visual.cs b/CSharpBible/Games/Werner_Flaschbier/View/Visual.cs
index 21df70349..baf8a8533 100644
--- a/CSharpBible/Games/Werner_Flaschbier/View/Visual.cs
+++ b/CSharpBible/Games/Werner_Flaschbier/View/Visual.cs
@@ -34,12 +34,13 @@ public class Visual : IVisual {
///
/// The game
///
- private IWernerViewModel? _game;
+ private IWernerViewModel _viewModel;
+ private readonly ITileDef _tileDef;
- ///
- /// My console
- ///
- private IConsole _console ;
+ ///
+ /// My console
+ ///
+ private IConsole _console ;
///
/// The key action
@@ -61,18 +62,19 @@ public class Visual : IVisual {
#endregion
#region Methods
- public Visual(IWernerViewModel viewModel,IConsole console)
+ public Visual(IWernerViewModel viewModel,IConsole console, ITileDef tileDef)
{
- _game = viewModel;
- _game.PropertyChanged += OnPropertyChanged;
- _console = console;
+ _viewModel = viewModel;
+ _viewModel.PropertyChanged += OnPropertyChanged;
+ _tileDef = tileDef;
+ _console = console;
FullRedraw();
}
- private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Tiles")
- G_visUpdate(sender, _game.HalfStep);
+ G_visUpdate(sender, _viewModel!.HalfStep);
else if (e.PropertyName == "Level")
FullRedraw();
}
@@ -96,20 +98,20 @@ private void G_visUpdate(object? sender, bool e)
{
List<(Point, Tiles, Point)> diffFields = new();
var p = new Point();
- if (_game==null) return;
+ if (_viewModel==null) return;
- for (p.Y = 0; p.Y < _game.size.Height; p.Y++)
- for (p.X = 0; p.X < _game.size.Width; p.X++)
+ for (p.Y = 0; p.Y < _viewModel.size.Height; p.Y++)
+ for (p.X = 0; p.X < _viewModel.size.Width; p.X++)
{
- var td = _game.Tiles[p];
- if ((Tiles)td != _buffer[p.X + p.Y * _game.size.Width] || (IsEnemy((Tiles)td) && _game.OldPos(p)!=p))
+ var td = _viewModel.Tiles[p];
+ if ((Tiles)td != _buffer[p.X + p.Y * _viewModel.size.Width] || (IsEnemy((Tiles)td) && _viewModel.OldPos(p)!=p))
{
Point pp = new Point(p.X,p.Y);
#pragma warning disable CS8604 // Mgliches Nullverweisargument.
- diffFields.Add((pp, (Tiles)td, _game.OldPos(p)));
+ diffFields.Add((pp, (Tiles)td, _viewModel.OldPos(p)));
#pragma warning restore CS8604 // Mgliches Nullverweisargument.
if (!e)
- _buffer[p.X + p.Y * _game.size.Width] = (Tiles)td;
+ _buffer[p.X + p.Y * _viewModel.size.Width] = (Tiles)td;
}
}
if (e)
@@ -132,9 +134,9 @@ private void G_visUpdate(object? sender, bool e)
if (f.Item1.X != f.Item3.X && f.Item1.Y != f.Item3.Y)
{
var p1 = new Point(f.Item1.X, f.Item3.Y);
- WriteTile(p1, (Tiles)_game.Tiles[p1]);
+ WriteTile(p1, (Tiles)_viewModel.Tiles[p1]);
var p2 = new Point(f.Item3.X, f.Item1.Y);
- WriteTile(p2, (Tiles)_game.Tiles[p2]);
+ WriteTile(p2, (Tiles)_viewModel.Tiles[p2]);
}
WriteTile(f.Item1, f.Item2);
}
@@ -150,13 +152,13 @@ private void G_visUpdate(object? sender, bool e)
public void FullRedraw(object? sender=null,EventArgs? e=null)
{
// basic Checks
- if (_game == null) return;
+ if (_viewModel == null) return;
// Draw playfield
Point p = new Point();
- for (p.Y = 0; p.Y < _game.size.Height; p.Y++)
- for (p.X = 0; p.X < _game.size.Width; p.X++)
- WriteTile(p, _buffer[p.X + p.Y * _game.size.Width] = (Tiles)_game.Tiles[p]);
+ for (p.Y = 0; p.Y < _viewModel.size.Height; p.Y++)
+ for (p.X = 0; p.X < _viewModel.size.Width; p.X++)
+ WriteTile(p, _buffer[p.X + p.Y * _viewModel.size.Width] = (Tiles)_viewModel.Tiles[p]);
// Draw statistics
ShowStatistics();
@@ -167,11 +169,11 @@ public void FullRedraw(object? sender=null,EventArgs? e=null)
///
private void ShowStatistics()
{
- if (_game == null) return;
+ if (_viewModel == null) return;
_console.SetCursorPosition(0, 24);
_console.BackgroundColor = ConsoleColor.Black;
_console.ForegroundColor = ConsoleColor.Yellow;
- _console.Write($"\t{_game.Level + 1}\t\t{_game.Score}\t\t{_game.Lives}/{_game.MaxLives} \t\t{Math.Floor(_game.TimeLeft)}\t\x08");
+ _console.Write($"\t{_viewModel.Level + 1}\t\t{_viewModel.Score}\t\t{_viewModel.Lives}/{_viewModel.MaxLives} \t\t{Math.Floor(_viewModel.TimeLeft)}\t\x08");
}
///
@@ -182,15 +184,14 @@ private void ShowStatistics()
public void WriteTile(PointF p, Tiles tile)
{
Size s = new Size(4, 2);
- var colors = VTileDef.GetTileColors(tile);
- var sTileStr = VTileDef.GetTileStr(tile);
- for (int i = 0; i < sTileStr.Length; i++)
- for (int x = 0; x < sTileStr[i].Length; x++)
+ var tDef = _tileDef.GetTileDef(tile);
+ for (int i = 0; i < tDef.lines.Length; i++)
+ for (int x = 0; x < tDef.lines[i].Length; x++)
{
- _console.ForegroundColor = colors[x + i * s.Width].foreGround;
- _console.BackgroundColor = colors[x + i * s.Width].backGround;
+ _console.ForegroundColor = tDef.colors[x + i * s.Width].fgr;
+ _console.BackgroundColor = tDef.colors[x + i * s.Width].bgr;
_console.SetCursorPosition((int)(p.X * s.Width) + x, (int)(p.Y * s.Height) + i);
- _console.Write(sTileStr[i][x]);
+ _console.Write(tDef.lines[i][x]);
}
}
@@ -235,7 +236,7 @@ public bool CheckUserAction()
result = true;
}
}
- _game?.HandleUserAction(action);
+ _viewModel?.HandleUserAction(action);
return result;
}
diff --git a/CSharpBible/Games/Werner_Flaschbier/ViewModels/IWernerViewModel.cs b/CSharpBible/Games/Werner_Flaschbier/ViewModels/IWernerViewModel.cs
new file mode 100644
index 000000000..b6ae1f93b
--- /dev/null
+++ b/CSharpBible/Games/Werner_Flaschbier/ViewModels/IWernerViewModel.cs
@@ -0,0 +1,23 @@
+using System.ComponentModel;
+using System.Drawing;
+
+namespace Werner_Flaschbier_Base.ViewModels;
+
+public interface IWernerViewModel : INotifyPropertyChanged, INotifyPropertyChanging
+{
+ public interface ITileProxy
+ {
+ System.Enum this[Point p] { get; }
+ }
+ ITileProxy Tiles { get; }
+ Size size { get; }
+ int Level { get; }
+ int Score { get; }
+ int Lives { get; }
+ int MaxLives { get; }
+ float TimeLeft { get; }
+ bool HalfStep { get; }
+
+ void HandleUserAction(UserAction action);
+ Point OldPos(Point p);
+}
\ No newline at end of file
diff --git a/CSharpBible/Games/Werner_Flaschbier/ViewModels/WernerViewModel.cs b/CSharpBible/Games/Werner_Flaschbier/ViewModels/WernerViewModel.cs
new file mode 100644
index 000000000..3ef28bd40
--- /dev/null
+++ b/CSharpBible/Games/Werner_Flaschbier/ViewModels/WernerViewModel.cs
@@ -0,0 +1,94 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Werner_Flaschbier_Base.Model;
+
+namespace Werner_Flaschbier_Base.ViewModels;
+
+public partial class WernerViewModel : ObservableObject, IWernerViewModel
+{
+ public class _TileProxy(IWernerGame game) : IWernerViewModel.ITileProxy
+ {
+ IWernerGame _game = game;
+ public Enum this[Point p]
+ { get => _game[p]; }
+ }
+ #region
+ private IWernerGame _game;
+ private bool _halfStep;
+
+ public IWernerViewModel.ITileProxy Tiles { get; }
+
+ public Size size => _game.size;
+
+ public int Level => _game.Level;
+
+ public int Score => _game.Score;
+
+ public int Lives => _game.Lives;
+
+ public int MaxLives => _game.MaxLives;
+
+ public float TimeLeft => _game.TimeLeft;
+
+ public bool HalfStep => _halfStep;
+ #endregion
+
+ #region Methods
+ public WernerViewModel(IWernerGame game) {
+ _game = game;
+ Tiles = new _TileProxy(game);
+ _game.visUpdate += (s, e) =>
+ {
+ _halfStep = e;
+ OnPropertyChanged(nameof(Tiles));
+ };
+ _game.visFullRedraw += (s, e) => OnPropertyChanged(nameof(Level));
+ }
+
+ ///
+ /// Handles the user action.
+ ///
+ /// The action.
+ public void HandleUserAction(UserAction action)
+ {
+ switch (action)
+ {
+ case UserAction.Quit:
+ _game.ReqQuit();
+ break;
+ case UserAction.Help:
+ _game.ReqHelp();
+ break;
+ case UserAction.Restart:
+ _game.ReqRestart();
+ break;
+ case UserAction.Nop:
+ break;
+ case UserAction.NextLvl:
+ _game.NextLvl();
+ break;
+ case UserAction.PrevLvl:
+ _game.PrevLvl();
+ break;
+ default:
+ if ((int)action < typeof(Direction).GetEnumValues().Length)
+ {
+ _game.MovePlayer((Direction)action);
+ }
+ break;
+ }
+ _game.HandleGameLogic();
+ }
+
+ public Point OldPos(Point p)
+ {
+ return _game.OldPos(p);
+ }
+
+ #endregion
+}
diff --git a/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base.csproj b/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base.csproj
index 2ffe1b7dd..517785552 100644
--- a/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base.csproj
+++ b/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base.csproj
@@ -18,6 +18,9 @@
+
+
+
diff --git a/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base_win.csproj b/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base_win.csproj
index 0bfb35753..ae96d7f86 100644
--- a/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base_win.csproj
+++ b/CSharpBible/Games/Werner_Flaschbier/Werner_Flaschbier_Base_win.csproj
@@ -18,6 +18,9 @@
+
+
+
diff --git a/CSharpBible/Games/Werner_Flaschbier_BaseTests/View/VisualTests.cs b/CSharpBible/Games/Werner_Flaschbier_BaseTests/View/VisualTests.cs
index 73d17a654..3b850b536 100644
--- a/CSharpBible/Games/Werner_Flaschbier_BaseTests/View/VisualTests.cs
+++ b/CSharpBible/Games/Werner_Flaschbier_BaseTests/View/VisualTests.cs
@@ -76,8 +76,11 @@ public class VisualTests
\c0E\t2\t\t0\t\t10/10\t\t99\t\c00";
TstConsole? _testConsole;
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend.
private IWernerViewModel _model;
+ private VTileDef _tileDef;
private Visual testClass;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend.
///
/// Initializes this instance.
@@ -87,7 +90,8 @@ public void Init()
{
_testConsole ??= new TstConsole();
_model = Substitute.For();
- testClass = new Visual(_model,_testConsole);
+ _tileDef = new VTileDef();
+ testClass = new Visual(_model,_testConsole,_tileDef);
}
///
diff --git a/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_BaseTests.csproj b/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_BaseTests.csproj
new file mode 100644
index 000000000..8082484f4
--- /dev/null
+++ b/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_BaseTests.csproj
@@ -0,0 +1,31 @@
+
+
+
+ net6.0-windows;net7.0-windows;net8.0-windows;net9.0-windows
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_ConsoleTests.csproj b/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_ConsoleTests.csproj
new file mode 100644
index 000000000..35751d907
--- /dev/null
+++ b/CSharpBible/Games/Werner_Flaschbier_BaseTests/Werner_Flaschbier_ConsoleTests.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net6.0-windows;net7.0-windows;net8.0-windows;net9.0-windows
+ false
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CSharpBible/Libraries/BaseLib/BaseLib_net.csproj b/CSharpBible/Libraries/BaseLib/BaseLib_net.csproj
index cffdfcc5c..94a815635 100644
--- a/CSharpBible/Libraries/BaseLib/BaseLib_net.csproj
+++ b/CSharpBible/Libraries/BaseLib/BaseLib_net.csproj
@@ -2,7 +2,7 @@
Library
- net6.0;net7.0;net8.0;net481-windows;net48-windows;net472-windows;net462-windows
+ net6.0;net7.0;net8.0;net9.0;net481-windows;net48-windows;net472-windows;net462-windows
True
@@ -13,7 +13,6 @@
-
@@ -21,5 +20,6 @@
-
-
+
+
+
\ No newline at end of file
diff --git a/CSharpBible/Libraries/MVVM_BaseLib/Helper/CRandom.cs b/CSharpBible/Libraries/MVVM_BaseLib/Helper/CRandom.cs
new file mode 100644
index 000000000..b52be079c
--- /dev/null
+++ b/CSharpBible/Libraries/MVVM_BaseLib/Helper/CRandom.cs
@@ -0,0 +1,22 @@
+using BaseLib.Interfaces;
+using System;
+
+namespace BaseLib.Helper;
+
+public class CRandom : IRandom
+{
+ private Random _random;
+
+ public CRandom()
+ {
+ _random = new Random();
+ }
+
+ public int Next(int v1, int v2) => v2 != -1 || v1 < v2 ? _random.Next(v1, v2) : _random.Next(v1);
+
+ public double NextDouble() => _random.NextDouble();
+
+ public int NextInt() => _random.Next();
+
+ public void Seed(int value) => _random = new Random(value);
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue.sln b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue.sln
new file mode 100644
index 000000000..0dd5f5ee8
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue.sln
@@ -0,0 +1,67 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Projektmappenelemente", "Projektmappenelemente", "{658BD492-33FF-4995-AAE7-4F6894E92F0C}"
+ ProjectSection(SolutionItems) = preProject
+ MVVM_Tutorial.props = MVVM_Tutorial.props
+ MVVM_Tutorial_net.props = MVVM_Tutorial_net.props
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_BaseLib", "..\Libraries\MVVM_BaseLib\MVVM_BaseLib.csproj", "{890CF504-3814-443B-9EE6-E8BCACF68203}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{AF041458-CF94-4D6D-BB0F-8BC50F4F099C}"
+ ProjectSection(SolutionItems) = preProject
+ ..\Libraries\Libraries_net.props = ..\Libraries\Libraries_net.props
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_BaseLibTests", "..\Libraries\MVVM_BaseLibTests\MVVM_BaseLibTests.csproj", "{66EB60F2-523D-47C8-95EA-C7E10759E239}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_99_SomeIssue", "MVVM_99_SomeIssue\MVVM_99_SomeIssue.csproj", "{16A3E367-674C-4959-8B31-7681B0E8258C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_99_SomeIssue_net", "MVVM_99_SomeIssue\MVVM_99_SomeIssue_net.csproj", "{D6BFC652-822A-4E7D-9846-7F529C584BAC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_99_SomeIssue_netTests", "MVVM_99_SomeIssueTests\MVVM_99_SomeIssue_netTests.csproj", "{A7844F45-74D9-4A81-9C27-D0E17ED0F851}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_99_SomeIssueTests", "MVVM_99_SomeIssueTests\MVVM_99_SomeIssueTests.csproj", "{7FF12BBB-AA2E-48C1-B283-0665570902F8}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {890CF504-3814-443B-9EE6-E8BCACF68203}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {890CF504-3814-443B-9EE6-E8BCACF68203}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {890CF504-3814-443B-9EE6-E8BCACF68203}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {890CF504-3814-443B-9EE6-E8BCACF68203}.Release|Any CPU.Build.0 = Release|Any CPU
+ {66EB60F2-523D-47C8-95EA-C7E10759E239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66EB60F2-523D-47C8-95EA-C7E10759E239}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66EB60F2-523D-47C8-95EA-C7E10759E239}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66EB60F2-523D-47C8-95EA-C7E10759E239}.Release|Any CPU.Build.0 = Release|Any CPU
+ {16A3E367-674C-4959-8B31-7681B0E8258C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {16A3E367-674C-4959-8B31-7681B0E8258C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {16A3E367-674C-4959-8B31-7681B0E8258C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {16A3E367-674C-4959-8B31-7681B0E8258C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D6BFC652-822A-4E7D-9846-7F529C584BAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D6BFC652-822A-4E7D-9846-7F529C584BAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D6BFC652-822A-4E7D-9846-7F529C584BAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D6BFC652-822A-4E7D-9846-7F529C584BAC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A7844F45-74D9-4A81-9C27-D0E17ED0F851}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A7844F45-74D9-4A81-9C27-D0E17ED0F851}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A7844F45-74D9-4A81-9C27-D0E17ED0F851}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A7844F45-74D9-4A81-9C27-D0E17ED0F851}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7FF12BBB-AA2E-48C1-B283-0665570902F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7FF12BBB-AA2E-48C1-B283-0665570902F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7FF12BBB-AA2E-48C1-B283-0665570902F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7FF12BBB-AA2E-48C1-B283-0665570902F8}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {890CF504-3814-443B-9EE6-E8BCACF68203} = {AF041458-CF94-4D6D-BB0F-8BC50F4F099C}
+ {66EB60F2-523D-47C8-95EA-C7E10759E239} = {AF041458-CF94-4D6D-BB0F-8BC50F4F099C}
+ EndGlobalSection
+EndGlobal
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml
new file mode 100644
index 000000000..de9b986e0
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml.cs
new file mode 100644
index 000000000..5c01749b0
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/App.xaml.cs
@@ -0,0 +1,43 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue
+// Author : Mir
+// Created : 08-11-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 08-24-2022
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2022
+//
+//
+// ***********************************************************************
+using BaseLib.Helper;
+using BaseLib.Interfaces;
+using Microsoft.Extensions.DependencyInjection;
+using MVVM.View.Extension;
+using MVVM_99_SomeIssue.Models;
+using System.Windows;
+
+namespace MVVM_99_SomeIssue
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ protected override void OnStartup(StartupEventArgs e)
+ {
+ var sc = new ServiceCollection()
+ .AddTransient()
+ .AddTransient()
+ .AddSingleton();
+
+ var bc = sc.BuildServiceProvider();
+
+ IoC.Configure(bc);
+ }
+ }
+}
+namespace MVVM_99_SomeIssue.Models { }
+namespace MVVM_99_SomeIssue.ValueConverter { }
+namespace MVVM_99_SomeIssue.Services { }
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/AssemblyInfo.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/AssemblyInfo.cs
new file mode 100644
index 000000000..f60efc019
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue.csproj b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue.csproj
new file mode 100644
index 000000000..5d87bdcae
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue.csproj
@@ -0,0 +1,40 @@
+
+
+
+ WinExe
+ net462-windows;net472-windows;net48-windows;net481-windows
+ true
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ True
+ Settings.settings
+
+
+
+
+ PublicResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+ PublicSettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue_net.csproj b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue_net.csproj
new file mode 100644
index 000000000..977e7a83b
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MVVM_99_SomeIssue_net.csproj
@@ -0,0 +1,40 @@
+
+
+
+ WinExe
+ net6.0-windows;net7.0-windows;net8.0-windows;net9.0-windows
+ true
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ True
+ Settings.settings
+
+
+
+
+ PublicResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+ PublicSettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml
new file mode 100644
index 000000000..1a157ed14
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml.cs
new file mode 100644
index 000000000..6438f00f9
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/MainWindow.xaml.cs
@@ -0,0 +1,31 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue
+// Author : Mir
+// Created : 08-11-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 08-24-2022
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2022
+//
+//
+// ***********************************************************************
+using System.Windows;
+
+namespace MVVM_99_SomeIssue
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/.info b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/.info
new file mode 100644
index 000000000..62f215ed0
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/.info
@@ -0,0 +1 @@
+Folder for Models
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/ISomeIssueModel.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/ISomeIssueModel.cs
new file mode 100644
index 000000000..ecc73970d
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/ISomeIssueModel.cs
@@ -0,0 +1,41 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue
+// Author : Mir
+// Created : 05-19-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-19-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using System;
+using System.ComponentModel;
+
+///
+/// The Models namespace.
+///
+///
+namespace MVVM_99_SomeIssue.Models
+{
+ ///
+ /// Interface ISomeIssueModel
+ ///
+ ///
+ public interface ISomeIssueModel
+ {
+ ///
+ /// Gets the now.
+ ///
+ /// The now.
+ ///
+ DateTime Now { get; }
+ ///
+ /// Occurs when [property changed].
+ ///
+ ///
+ event PropertyChangedEventHandler PropertyChanged;
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SimpleLog.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SimpleLog.cs
new file mode 100644
index 000000000..a227287ac
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SimpleLog.cs
@@ -0,0 +1,30 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue
+// Author : Mir
+// Created : 08-11-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 08-24-2022
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2022
+//
+//
+// ***********************************************************************
+using BaseLib.Interfaces;
+using System;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace MVVM_99_SomeIssue;
+
+public class SimpleLog(ISysTime sysTime):ILog
+{
+ public static Action LogAction { get; set; } = (message) => Debug.WriteLine(message);
+ ISysTime _sysTime { get; } = sysTime;
+
+ public void Log(string message)
+ => LogAction($"{_sysTime.Now.ToString(CultureInfo.InvariantCulture)}: Msg: {message}");
+ public void Log(string message, Exception exception)
+ => LogAction($"{_sysTime.Now.ToString(CultureInfo.InvariantCulture)}: Err: {message}, {exception}");
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SomeIssueModel.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SomeIssueModel.cs
new file mode 100644
index 000000000..95f458e31
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Models/SomeIssueModel.cs
@@ -0,0 +1,84 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue
+// Author : Mir
+// Created : 05-19-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-19-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using BaseLib.Interfaces;
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Timers;
+
+///
+/// The Models namespace.
+///
+///
+namespace MVVM_99_SomeIssue.Models
+{
+ ///
+ /// Class SomeIssueModel.
+ /// Implements the
+ /// Implements the
+ ///
+ ///
+ ///
+ ///
+ public partial class SomeIssueModel :ObservableObject, ISomeIssueModel
+ {
+ private const string csApplStart = "Application startet";
+#if !NET5_0_OR_GREATER
+ private const string csApplEnded = "Application ended";
+#endif
+ #region Properties
+ ///
+ /// The timer
+ ///
+ ///
+ private readonly Timer _timer;
+ private readonly ISysTime _systime;
+ private readonly ILog _log;
+
+ ///
+ /// Gets the now.
+ ///
+ /// The now.
+ ///
+ public DateTime Now { get => _systime.Now; }
+ #endregion
+
+ #region Methods
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ public SomeIssueModel(ISysTime sysTime,ILog log)
+ {
+ _systime = sysTime;
+ _log = log;
+ _log.Log(csApplStart);
+ _timer = new(250d);
+ _timer.Elapsed += (s, e) => OnPropertyChanged(nameof(Now));
+ _timer.Start();
+ }
+
+#if !NET5_0_OR_GREATER
+ ///
+ /// Finalizes an instance of the class.
+ ///
+ ~SomeIssueModel()
+ {
+ _timer.Stop();
+ _log.Log(csApplEnded);
+ return;
+ }
+#endif
+ #endregion
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.Designer.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..dedf68853
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.Designer.cs
@@ -0,0 +1,119 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion:4.0.30319.42000
+//
+// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
+// der Code erneut generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace MVVM_99_SomeIssue.Properties {
+ using System;
+
+
+ ///
+ /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
+ ///
+ // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
+ // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
+ // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
+ // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ public class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MVVM_99_SomeIssue.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
+ /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Zeichenfolge, die MVVM-SomeIssue using Community-Toolkit ähnelt.
+ ///
+ public static string Description {
+ get {
+ return ResourceManager.GetString("Description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Zeichenfolge, die <Page
+ /// xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ /// xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ /// xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ /// xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ /// xmlns:local="clr-namespace:MVVM_99_SomeIssue.Views"
+ /// xmlns:p="clr-namespace:MVVM_99_SomeIssue.Properties"
+ /// xmlns:vc="clr-namespace:MVVM_99_SomeIssue.ValueConverter"
+ /// xmlns:mvvm="clr-namespace: [Rest der Zeichenfolge wurde abgeschnitten]"; ähnelt.
+ ///
+ public static string SomeIssueView {
+ get {
+ return ResourceManager.GetString("SomeIssueView", resourceCulture);
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Zeichenfolge, die // ***********************************************************************
+ ///// Assembly : MVVM_99_SomeIssue
+ ///// Author : Mir
+ ///// Created : 08-11-2022
+ /////
+ ///// Last Modified By : Mir
+ ///// Last Modified On : 08-24-2022
+ ///// ***********************************************************************
+ ///// <copyright file="MainWindowViewModel.cs" company="JC-Soft">
+ ///// Copyright © JC-Soft 2022
+ ///// </copyright>
+ ///// <summary></summary>
+ ///// ************************************************** [Rest der Zeichenfolge wurde abgeschnitten]"; ähnelt.
+ ///
+ public static string SomeIssueViewModel {
+ get {
+ return ResourceManager.GetString("SomeIssueViewModel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Zeichenfolge, die CT-SomeIssue-View ähnelt.
+ ///
+ public static string Title {
+ get {
+ return ResourceManager.GetString("Title", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.resx b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.resx
new file mode 100644
index 000000000..17780c00a
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Resources.resx
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ MVVM-SomeIssue using Community-Toolkit
+
+
+
+ ..\Views\SomeIssueView.xaml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
+
+ ..\ViewModels\SomeIssueViewModel.cs;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
+
+ CT-SomeIssue-View
+
+
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.Designer.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.Designer.cs
new file mode 100644
index 000000000..b9e5e754f
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion:4.0.30319.42000
+//
+// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
+// der Code erneut generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace MVVM_99_SomeIssue.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")]
+ public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.settings b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.settings
new file mode 100644
index 000000000..049245f40
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Properties/Settings.settings
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/.info b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/.info
new file mode 100644
index 000000000..b4bc464df
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/.info
@@ -0,0 +1 @@
+Folder for ValueConverters
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/DateTimeValueConverter.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/DateTimeValueConverter.cs
new file mode 100644
index 000000000..7fd3bcbee
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ValueConverters/DateTimeValueConverter.cs
@@ -0,0 +1,63 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue
+// Author : Mir
+// Created : 07-03-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 07-04-2022
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace MVVM_99_SomeIssue.ValueConverter
+{
+ ///
+ /// Class CurrencyValueConverter.
+ /// Implements the
+ ///
+ ///
+ public class DateTimeValueConverter : IValueConverter
+ {
+ ///
+ /// Converts a value.
+ ///
+ /// The value produced by the binding source.
+ /// The type of the binding target property.
+ /// The converter parameter to use.
+ /// The culture to use in the converter.
+ /// A converted value. If the method returns , the valid null value is used.
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is DateTime dt)
+ if (parameter is string spar)
+ return dt.ToString(spar);
+ else
+ return dt.ToString(culture);
+ else
+ return value?.ToString() ?? "";
+
+ }
+
+ ///
+ /// Converts a value.
+ ///
+ /// The value that is produced by the binding target.
+ /// The type to convert to.
+ /// The converter parameter to use.
+ /// The culture to use in the converter.
+ /// A converted value. If the method returns , the valid null value is used.
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is string sval && DateTime.TryParse(sval.Trim(),culture, DateTimeStyles.AssumeLocal, out var dt))
+ return dt;
+ else
+ return DateTime.MinValue;
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/.info b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/.info
new file mode 100644
index 000000000..a3ed848fb
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/.info
@@ -0,0 +1 @@
+Folder for ViewModels
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/MainWindowViewModel.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/MainWindowViewModel.cs
new file mode 100644
index 000000000..e874122f4
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/MainWindowViewModel.cs
@@ -0,0 +1,47 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue
+// Author : Mir
+// Created : 08-11-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 08-24-2022
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2022
+//
+//
+// ***********************************************************************
+using MVVM.ViewModel;
+
+namespace MVVM_99_SomeIssue.ViewModels
+{
+ ///
+ /// Class MainWindowViewModel.
+ /// Implements the
+ ///
+ ///
+ public class MainWindowViewModel : BaseViewModelCT
+ {
+ #region Properties
+ #endregion
+ #region Methods
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public MainWindowViewModel()
+ {
+
+ }
+
+#if !NET5_0_OR_GREATER
+ ///
+ /// Finalizes an instance of the class.
+ ///
+ ~MainWindowViewModel()
+ {
+ return;
+ }
+#endif
+ #endregion
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/SomeIssueViewModel.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/SomeIssueViewModel.cs
new file mode 100644
index 000000000..24f83d50a
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/ViewModels/SomeIssueViewModel.cs
@@ -0,0 +1,55 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue
+// Author : Mir
+// Created : 08-11-2022
+//
+// Last Modified By : Mir
+// Last Modified On : 08-24-2022
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2022
+//
+//
+// ***********************************************************************
+using MVVM.View.Extension;
+using MVVM.ViewModel;
+using MVVM_99_SomeIssue.Models;
+using System;
+using System.ComponentModel;
+
+namespace MVVM_99_SomeIssue.ViewModels;
+
+///
+/// Class MainWindowViewModel.
+/// Implements the
+///
+///
+public partial class SomeIssueViewModel : BaseViewModelCT
+{
+ #region Properties
+ private readonly ISomeIssueModel _model;
+
+ public DateTime Now => _model.Now;
+ #endregion
+
+ #region Methods
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SomeIssueViewModel():this(IoC.GetRequiredService())
+ {
+ }
+
+ public SomeIssueViewModel(ISomeIssueModel model)
+ {
+ _model = model;
+ _model.PropertyChanged += OnMPropertyChanged;
+ }
+
+ private void OnMPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ OnPropertyChanged(e.PropertyName);
+ }
+
+ #endregion
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/.info b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/.info
new file mode 100644
index 000000000..65a00d680
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/.info
@@ -0,0 +1 @@
+Folder for Views
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml
new file mode 100644
index 000000000..8d86d8941
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml.cs
new file mode 100644
index 000000000..25b9c440b
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssue/Views/SomeIssueView.xaml.cs
@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace MVVM_99_SomeIssue.Views
+{
+ ///
+ /// Interaktionslogik für SomeIssueView.xaml
+ ///
+ public partial class SomeIssueView : Page
+ {
+ public SomeIssueView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/AppTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/AppTests.cs
new file mode 100644
index 000000000..695996c10
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/AppTests.cs
@@ -0,0 +1,65 @@
+using BaseLib.Interfaces;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using MVVM.View.Extension;
+using MVVM_99_SomeIssue.Models;
+using NSubstitute;
+using System;
+
+namespace MVVM_99_SomeIssue.Tests
+{
+ internal class TestApp : App
+ {
+ public void DoStartUp()
+ {
+ OnStartup(null);
+ }
+ }
+ [TestClass()]
+ public class AppTests
+ {
+ static TestApp app = new();
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+ private Func _gsold;
+ private Func _grsold;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+ private ISysTime? _sysTime;
+ private ILog? _log;
+
+ ///
+ /// Initializes this instance.
+ ///
+ ///
+ [TestInitialize]
+ public void Init()
+ {
+ _gsold = IoC.GetSrv;
+ _grsold = IoC.GetReqSrv;
+ IoC.GetReqSrv = (t) =>t switch {
+ _ when t == typeof(ILog) => _log ??= Substitute.For(),
+ _ when t == typeof(ISysTime) => _sysTime ??= Substitute.For(),
+ _ when t == typeof(ISomeIssueModel) => new SomeIssueModel(IoC.GetRequiredService(),IoC.GetRequiredService()),
+ _ => throw new ArgumentException() };
+ }
+
+ [TestCleanup]
+ public void CleanUp()
+ {
+ IoC.GetSrv = _gsold;
+ IoC.GetReqSrv = _grsold;
+ }
+
+ [TestMethod]
+ public void AppTest()
+ {
+ Assert.IsNotNull(app);
+ }
+
+ [TestMethod]
+ public void AppTest2()
+ {
+ app.DoStartUp();
+ Assert.IsNotNull(IoC.GetReqSrv(typeof(ISomeIssueModel)));
+ Assert.IsNull(IoC.GetSrv(typeof(App)));
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssueTests.csproj b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssueTests.csproj
new file mode 100644
index 000000000..a1e06aeb1
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssueTests.csproj
@@ -0,0 +1,27 @@
+
+
+
+ net462-windows;net472-windows;net48-windows;net481-windows
+ true
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssue_netTests.csproj b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssue_netTests.csproj
new file mode 100644
index 000000000..776439cce
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/MVVM_99_SomeIssue_netTests.csproj
@@ -0,0 +1,24 @@
+
+
+
+ net6.0-windows;net7.0-windows;net8.0-windows;net9.0-windows
+ true
+ false
+ true
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SimpleLogTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SimpleLogTests.cs
new file mode 100644
index 000000000..7e7393948
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SimpleLogTests.cs
@@ -0,0 +1,71 @@
+using BaseLib.Interfaces;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using MVVM.ViewModel;
+using MVVM.ViewModel.Tests;
+using NSubstitute;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MVVM_99_SomeIssue.Models.Tests;
+
+[TestClass]
+public class SimpleLogTests:BaseTestViewModel
+{
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend.
+ private Action _gsOld;
+ private SimpleLog simpleLog;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Fügen Sie ggf. den „erforderlichen“ Modifizierer hinzu, oder deklarieren Sie den Modifizierer als NULL-Werte zulassend.
+ private ISysTime? _sysTime;
+
+
+ [TestInitialize]
+ public void TestInitialize()
+ {
+ _gsOld= SimpleLog.LogAction;
+ _gsOld("Test message");
+ SimpleLog.LogAction = DoLog;
+ _sysTime = Substitute.For();
+ _sysTime.Now.Returns(new DateTime(2022, 08, 24, 12, 0, 0));
+ simpleLog = new SimpleLog(_sysTime);
+ }
+
+ [TestCleanup]
+ public void TestCleanup()
+ {
+ SimpleLog.LogAction = _gsOld;
+ }
+
+ [DataTestMethod]
+ [DataRow("Test message",new[] { "08/24/2022 12:00:00: Msg: Test message\r\n" })]
+ [DataRow(null, new[] { "08/24/2022 12:00:00: Msg: \r\n" })]
+ [DataRow("Some other test", new[] { "08/24/2022 12:00:00: Msg: Some other test\r\n" })]
+
+ public void LogTest(string message, string[] asExp)
+ {
+
+ // Act
+ simpleLog.Log(message);
+
+ // Assert
+ Assert.AreEqual(1, _sysTime.ReceivedCalls().Count());
+ Assert.AreEqual(asExp[0],DebugLog);
+ }
+
+ [TestMethod]
+ public void LogTest1()
+ {
+ // Arrange
+ var message = "Test message";
+ var exception = new Exception("Test exception");
+
+ // Act
+ simpleLog.Log(message, exception);
+
+ // Assert
+ Assert.AreEqual(1, _sysTime.ReceivedCalls().Count());
+ Assert.AreEqual("08/24/2022 12:00:00: Err: Test message, System.Exception: Test exception\r\n", DebugLog);
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SomeIssueModelTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SomeIssueModelTests.cs
new file mode 100644
index 000000000..d28ef186d
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Models/SomeIssueModelTests.cs
@@ -0,0 +1,73 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssueTests
+// Author : Mir
+// Created : 05-19-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-19-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using CommunityToolkit.Mvvm.ComponentModel;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using BaseLib.Interfaces;
+using MVVM.ViewModel;
+using NSubstitute;
+using System.ComponentModel;
+
+///
+/// The Tests namespace.
+///
+///
+namespace MVVM_99_SomeIssue.Models.Tests
+{
+ ///
+ /// Defines test class SomeIssueModelTests.
+ /// Implements the
+ ///
+ ///
+ ///
+ [TestClass()]
+ public class SomeIssueModelTests : BaseTestViewModel
+ {
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+ ///
+ /// The test model
+ ///
+ ///
+ SomeIssueModel testModel;
+ ISysTime _sysTime;
+ ILog _log;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+
+ ///
+ /// Initializes this instance.
+ ///
+ [TestInitialize]
+ public void Init()
+ {
+ _sysTime = Substitute.For();
+ _log = Substitute.For();
+ testModel = new(_sysTime,_log);
+ testModel.PropertyChanged += OnVMPropertyChanged;
+ if (testModel is INotifyPropertyChanging npchgn)
+ npchgn.PropertyChanging += OnVMPropertyChanging;
+ ClearLog();
+ }
+
+ ///
+ /// Defines the test method SetupTest.
+ ///
+ [TestMethod()]
+ public void SetupTest()
+ {
+ Assert.IsNotNull(testModel);
+ Assert.IsInstanceOfType(testModel, typeof(SomeIssueModel));
+ Assert.IsInstanceOfType(testModel, typeof(ObservableObject));
+ Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged));
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Properties/SettingsTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Properties/SettingsTests.cs
new file mode 100644
index 000000000..ff7cd0142
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Properties/SettingsTests.cs
@@ -0,0 +1,71 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue_netTests
+// Author : Mir
+// Created : 05-14-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-14-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Configuration;
+
+///
+/// The Tests namespace.
+///
+///
+namespace MVVM_99_SomeIssue.Properties.Tests
+{
+ ///
+ /// Defines test class SettingsTests.
+ ///
+ ///
+ [TestClass()]
+ public class SettingsTests
+ {
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+ ///
+ /// The test item
+ ///
+ ///
+ Settings testItem;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+
+ ///
+ /// Initializes this instance.
+ ///
+ ///
+ [TestInitialize]
+ public void Init()
+ {
+ testItem = new();
+ }
+
+ ///
+ /// Defines the test method SetupTest.
+ ///
+ ///
+ [TestMethod()]
+ public void SetupTest()
+ {
+ Assert.IsNotNull(testItem);
+ Assert.IsInstanceOfType(testItem, typeof(Settings));
+ Assert.IsInstanceOfType(testItem, typeof(ApplicationSettingsBase));
+ }
+ ///
+ /// Defines the test method DefaultInstanceTest.
+ ///
+ ///
+ [TestMethod()]
+ public void DefaultInstanceTest()
+ {
+ Assert.IsNotNull(Settings.Default);
+ Assert.IsInstanceOfType(Settings.Default, typeof(Settings));
+ Assert.IsInstanceOfType(Settings.Default, typeof(ApplicationSettingsBase));
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ValueConverters/DateTimeValueConverterTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ValueConverters/DateTimeValueConverterTests.cs
new file mode 100644
index 000000000..0e9b16ad4
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ValueConverters/DateTimeValueConverterTests.cs
@@ -0,0 +1,73 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssueTests
+// Author : Mir
+// Created : 05-11-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-11-2023
+// ***********************************************************************
+//
+// Copyright (c) JC-Soft. All rights reserved.
+//
+//
+// ***********************************************************************
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Globalization;
+
+///
+/// The Tests namespace.
+///
+///
+namespace MVVM_99_SomeIssue.ValueConverter.Tests
+{
+
+ ///
+ /// Defines test class CurrencyValueConverterTests.
+ ///
+ ///
+ [TestClass()]
+ public class DateTimeValueConverterTests
+ {
+ ///
+ /// The converter
+ ///
+ ///
+ readonly DateTimeValueConverter testConv = new();
+
+ ///
+ /// Converts the correctly formats value.
+ ///
+ /// The value.
+ /// The expected.
+ ///
+ [DataTestMethod]
+ [DataRow("2023-01-01 22:00",null, "01/01/2023 23:00:00")]
+ [DataRow("2023-05-02 12:30","MM/dd/yyyy", "05.02.2023")]
+ [DataRow("Hallo",null, "Hallo")]
+ [DataRow(null,null, "")]
+ public void ConvertTest(object? value, string? param, string expected)
+ {
+ if (value is string s && DateTime.TryParse(s, CultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal,out var dt)) value = dt;
+ var result = testConv.Convert(value, typeof(string), param, CultureInfo.InvariantCulture);
+ Assert.AreEqual(expected, result);
+ }
+
+ ///
+ /// Defines the test method ConvertBackTest.
+ ///
+ ///
+ [DataTestMethod]
+ [DataRow("2023-01-01 22:30", null, "01/01/2023 22:30:00")]
+ [DataRow("2023-05-02", "MM/dd/yyyy", "05.02.2023")]
+ [DataRow("01.01.0001 00:00:00", null, "Hallo")]
+ [DataRow("01.01.0001 00:00:00", "", 100)]
+ [DataRow("01.01.0001 00:00:00", "", null)]
+ public void ConvertBackTest(object? value, string? param, object? expected)
+ {
+ if (value is string s && DateTime.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var dt)) value = dt;
+ var result = testConv.ConvertBack(expected, typeof(DateTime), param, CultureInfo.InvariantCulture);
+ Assert.AreEqual(value, result);
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/MainWindowViewModelTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/MainWindowViewModelTests.cs
new file mode 100644
index 000000000..5e90b2bc0
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/MainWindowViewModelTests.cs
@@ -0,0 +1,58 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue_netTests
+// Author : Mir
+// Created : 05-14-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-19-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.ComponentModel;
+using MVVM.ViewModel;
+
+///
+/// The Tests namespace.
+///
+///
+namespace MVVM_99_SomeIssue.ViewModels.Tests
+{
+ ///
+ /// Defines test class MainWindowViewModelTests.
+ ///
+ ///
+ [TestClass()]
+ public class MainWindowViewModelTests : BaseTestViewModel
+ {
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+
+ ///
+ /// Initializes this instance.
+ ///
+ ///
+ [TestInitialize]
+ public override void Init()
+ {
+ base.Init();
+ }
+
+ ///
+ /// Defines the test method SetupTest.
+ ///
+ ///
+ [TestMethod()]
+ public void SetupTest()
+ {
+ Assert.IsNotNull(testModel);
+ Assert.IsInstanceOfType(testModel, typeof(MainWindowViewModel));
+ Assert.IsInstanceOfType(testModel, typeof(BaseViewModelCT));
+ Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged));
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/SomeIssueViewModelTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/SomeIssueViewModelTests.cs
new file mode 100644
index 000000000..50a049cd4
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/ViewModels/SomeIssueViewModelTests.cs
@@ -0,0 +1,80 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue_netTests
+// Author : Mir
+// Created : 05-14-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-14-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using System;
+using System.ComponentModel;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NSubstitute;
+using MVVM.ViewModel;
+using MVVM.View.Extension;
+using MVVM_99_SomeIssue.Models;
+
+///
+/// The Tests namespace.
+///
+///
+namespace MVVM_99_SomeIssue.ViewModels.Tests
+{
+ ///
+ /// Defines test class SomeIssueViewModelTests.
+ ///
+ ///
+ [TestClass()]
+ public class SomeIssueViewModelTests : BaseTestViewModel
+ {
+ /// The model
+ private ISomeIssueModel? _model;
+
+ ///
+ /// Initializes this instance.
+ ///
+ ///
+ [TestInitialize]
+ public override void Init()
+ {
+ IoC.GetReqSrv = (t) => t switch
+ {
+ Type _t when _t == typeof(ISomeIssueModel) => _model ??= Substitute.For(),
+ _ => throw new System.NotImplementedException($"No code for {t}")
+ };
+ base.Init();
+ _model.Now.Returns(new DateTime(2022, 08, 24, 12, 0, 0));
+ }
+
+ ///
+ /// Defines the test method SetupTest.
+ ///
+ ///
+ [TestMethod()]
+ public void SetupTest()
+ {
+ Assert.IsNotNull(testModel);
+ Assert.IsInstanceOfType(testModel, typeof(SomeIssueViewModel));
+ Assert.IsInstanceOfType(testModel, typeof(BaseViewModelCT));
+ Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged));
+ Assert.IsNotNull(_model);
+ }
+
+ [DataTestMethod()]
+ [DataRow(nameof(ISomeIssueModel.Now), new[] { "PropChg(MVVM_99_SomeIssue.ViewModels.SomeIssueViewModel,Now)=24.08.2022 12:00:00\r\n" })]
+ [DataRow("HasErrors", new[] { "PropChg(MVVM_99_SomeIssue.ViewModels.SomeIssueViewModel,HasErrors)=False\r\n" })]
+ [DataRow("Dummy", new[] { "PropChg(MVVM_99_SomeIssue.ViewModels.SomeIssueViewModel,Dummy)=\r\n" })]
+ public void PropertyChangedTest(string prop, string[] asExp)
+ {
+ _model.PropertyChanged += Raise.Event(_model, new PropertyChangedEventArgs(prop));
+ if (prop == nameof(ISomeIssueModel.Now))
+ _ = _model.Received(2).Now;
+ Assert.AreEqual(asExp[0], DebugLog);
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/MainWindowTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/MainWindowTests.cs
new file mode 100644
index 000000000..1ae34a0d6
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/MainWindowTests.cs
@@ -0,0 +1,62 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue_netTests
+// Author : Mir
+// Created : 05-14-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-14-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Threading;
+
+///
+/// The Tests namespace.
+///
+///
+namespace MVVM_99_SomeIssue.Views.Tests
+{
+ ///
+ /// Defines test class MainWindowTests.
+ ///
+ ///
+ [TestClass()]
+ public class MainWindowTests
+ {
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+ ///
+ /// The test view
+ ///
+ ///
+ MainWindow testView;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+
+ ///
+ /// Initializes this instance.
+ ///
+ ///
+ [TestInitialize]
+ public void Init()
+ {
+ var t = new Thread(() => testView = new());
+ t.SetApartmentState(ApartmentState.STA); //Set the thread to STA
+ t.Start();
+ t.Join(); //Wait for the thread to end
+ }
+
+ ///
+ /// Defines the test method MainWindowTest.
+ ///
+ ///
+ [TestMethod()]
+ public void MainWindowTest()
+ {
+ Assert.IsNotNull(testView);
+ Assert.IsInstanceOfType(testView, typeof(MainWindow));
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/SomeIssueViewTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/SomeIssueViewTests.cs
new file mode 100644
index 000000000..7b6c3f602
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_99_SomeIssueTests/Views/SomeIssueViewTests.cs
@@ -0,0 +1,62 @@
+// ***********************************************************************
+// Assembly : MVVM_99_SomeIssue_netTests
+// Author : Mir
+// Created : 05-14-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-14-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Threading;
+
+///
+/// The Tests namespace.
+///
+///
+namespace MVVM_99_SomeIssue.Views.Tests
+{
+ ///
+ /// Defines test class SomeIssueViewTests.
+ ///
+ ///
+ [TestClass()]
+ public class SomeIssueViewTests
+ {
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+ ///
+ /// The test view
+ ///
+ ///
+ SomeIssueView testView;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+
+ ///
+ /// Initializes this instance.
+ ///
+ ///
+ [TestInitialize]
+ public void Init()
+ {
+ var t = new Thread(() => testView = new());
+ t.SetApartmentState(ApartmentState.STA); //Set the thread to STA
+ t.Start();
+ t.Join(); //Wait for the thread to end
+ }
+
+ ///
+ /// Defines the test method MainWindowTest.
+ ///
+ ///
+ [TestMethod()]
+ public void MainWindowTest()
+ {
+ Assert.IsNotNull(testView);
+ Assert.IsInstanceOfType(testView, typeof(SomeIssueView));
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_AllExamples/Models/IAllExampleModel.cs b/CSharpBible/MVVM_Tutorial/MVVM_AllExamples/Models/IAllExampleModel.cs
new file mode 100644
index 000000000..58cb6debb
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_AllExamples/Models/IAllExampleModel.cs
@@ -0,0 +1,44 @@
+// ***********************************************************************
+// Assembly : MVVM_AllExamples
+// Author : Mir
+// Created : 05-19-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-19-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+
+///
+/// The Models namespace.
+///
+///
+namespace MVVM_AllExamples.Models
+{
+ ///
+ /// Interface ITemplateModel
+ ///
+ ///
+ public interface IAllExampleModel
+ {
+ ///
+ /// Gets the now.
+ ///
+ /// The now.
+ ///
+ DateTime Now { get; }
+ List Examples { get; }
+
+ ///
+ /// Occurs when [property changed].
+ ///
+ ///
+ event PropertyChangedEventHandler PropertyChanged;
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Models/AllExampleModelTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Models/AllExampleModelTests.cs
new file mode 100644
index 000000000..c081284c9
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Models/AllExampleModelTests.cs
@@ -0,0 +1,67 @@
+// ***********************************************************************
+// Assembly : MVVM_AllExamplesTests
+// Author : Mir
+// Created : 05-19-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-19-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using CommunityToolkit.Mvvm.ComponentModel;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using MVVM.ViewModel;
+using System.ComponentModel;
+
+///
+/// The Tests namespace.
+///
+///
+namespace MVVM_AllExamples.Models.Tests
+{
+ ///
+ /// Defines test class AllExampleModelTests.
+ /// Implements the
+ ///
+ ///
+ ///
+ [TestClass()]
+ public class AllExampleModelTests : BaseTestViewModel
+ {
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+ ///
+ /// The test model
+ ///
+ ///
+ AllExampleModel testModel;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+
+ ///
+ /// Initializes this instance.
+ ///
+ [TestInitialize]
+ public void Init()
+ {
+ testModel = new();
+ testModel.PropertyChanged += OnVMPropertyChanged;
+ if (testModel is INotifyPropertyChanging npchgn)
+ npchgn.PropertyChanging += OnVMPropertyChanging;
+ ClearLog();
+ }
+
+ ///
+ /// Defines the test method SetupTest.
+ ///
+ [TestMethod()]
+ public void SetupTest()
+ {
+ Assert.IsNotNull(testModel);
+ Assert.IsInstanceOfType(testModel, typeof(AllExampleModel));
+ Assert.IsInstanceOfType(testModel, typeof(ObservableObject));
+ Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged));
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/ViewModels/AllExamplesViewModelTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/ViewModels/AllExamplesViewModelTests.cs
new file mode 100644
index 000000000..2f761f0d5
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/ViewModels/AllExamplesViewModelTests.cs
@@ -0,0 +1,66 @@
+// ***********************************************************************
+// Assembly : MVVM_AllExamples_netTests
+// Author : Mir
+// Created : 05-14-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-14-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.ComponentModel;
+using MVVM.ViewModel;
+
+///
+/// The Tests namespace.
+///
+///
+namespace MVVM_AllExamples.ViewModels.Tests
+{
+ ///
+ /// Defines test class AllExampleViewModelTests.
+ ///
+ ///
+ [TestClass()]
+ public class AllExamplesViewModelTests:BaseTestViewModel
+ {
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+ ///
+ /// The test model
+ ///
+ ///
+ AllExamplesViewModel testModel;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+
+ ///
+ /// Initializes this instance.
+ ///
+ ///
+ [TestInitialize]
+ public void Init()
+ {
+ testModel = new();
+ testModel.PropertyChanged += OnVMPropertyChanged;
+ if (testModel is INotifyPropertyChanging npchgn)
+ npchgn.PropertyChanging += OnVMPropertyChanging;
+ ClearLog();
+ }
+
+ ///
+ /// Defines the test method SetupTest.
+ ///
+ ///
+ [TestMethod()]
+ public void SetupTest()
+ {
+ Assert.IsNotNull(testModel);
+ Assert.IsInstanceOfType(testModel, typeof(AllExamplesViewModel));
+ Assert.IsInstanceOfType(testModel, typeof(BaseViewModelCT));
+ Assert.IsInstanceOfType(testModel, typeof(INotifyPropertyChanged));
+ }
+ }
+}
diff --git a/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Views/AllExamplesViewTests.cs b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Views/AllExamplesViewTests.cs
new file mode 100644
index 000000000..abfa25636
--- /dev/null
+++ b/CSharpBible/MVVM_Tutorial/MVVM_AllExamplesTests/Views/AllExamplesViewTests.cs
@@ -0,0 +1,62 @@
+// ***********************************************************************
+// Assembly : MVVM_AllExamples_netTests
+// Author : Mir
+// Created : 05-14-2023
+//
+// Last Modified By : Mir
+// Last Modified On : 05-14-2023
+// ***********************************************************************
+//
+// Copyright © JC-Soft 2023
+//
+//
+// ***********************************************************************
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Threading;
+
+///
+/// The Tests namespace.
+///
+///
+namespace MVVM_AllExamples.Views.Tests
+{
+ ///
+ /// Defines test class AllExampleViewTests.
+ ///
+ ///
+ [TestClass()]
+ public class AllExampleViewTests
+ {
+#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+ ///
+ /// The test view
+ ///
+ ///
+ AllExamplesView testView;
+#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
+
+ ///
+ /// Initializes this instance.
+ ///
+ ///
+ [TestInitialize]
+ public void Init()
+ {
+ var t = new Thread(() => testView = new());
+ t.SetApartmentState(ApartmentState.STA); //Set the thread to STA
+ t.Start();
+ t.Join(); //Wait for the thread to end
+ }
+
+ ///
+ /// Defines the test method MainWindowTest.
+ ///
+ ///
+ [TestMethod()]
+ public void MainWindowTest()
+ {
+ Assert.IsNotNull(testView);
+ Assert.IsInstanceOfType(testView, typeof(AllExamplesView));
+ }
+ }
+}
diff --git a/CSharpBible/TestConsole/View/TestConsoleForm.cs b/CSharpBible/TestConsole/View/TestConsoleForm.cs
index c78ef30d6..379cab730 100644
--- a/CSharpBible/TestConsole/View/TestConsoleForm.cs
+++ b/CSharpBible/TestConsole/View/TestConsoleForm.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
@@ -143,16 +144,20 @@ public void Write(string? st)
/// The foreground color
///
private ConsoleColor foregroundColor = ConsoleColor.Gray;
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+
public ConsoleColor ForegroundColor { get => foregroundColor; set => foregroundColor = value; }
///
/// The background color
///
private ConsoleColor backgroundColor = ConsoleColor.Black;
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public ConsoleColor BackgroundColor { get => backgroundColor; set => backgroundColor = value; }
///
/// Gets or sets the width of the window.
///
/// The width of the window.
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int WindowWidth
{
get => ConsoleSize.Width;
@@ -166,6 +171,7 @@ public int WindowWidth
/// Gets or sets the height of the window.
///
/// The height of the window.
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int WindowHeight
{
get => ConsoleSize.Height;
@@ -234,8 +240,11 @@ public string Content { get
}
}
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ConsoleCharInfo[] ScreenBuffer { get => screenBuffer; set => screenBuffer = value; }
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ConsoleCharInfo[] OutBuffer { get => outBuffer; set => outBuffer = value; }
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Size ConsoleSize { get => consoleSize; set => consoleSize = value; }
///