Paia is a CLI framework that enables you to easily render and change between different views in a Console application.
If you like the project, please consider giving it a star to raise awareness!
- Usage
- Getting Started
- Create, Render and Change View
- Passing data between Views
- Dependency Injection
- More
- Maintainers
- License
See the sample projects for a basic usage of the framework.
The full project from the tutorial below can be found here.
Install Package
dotnet add package Paia
Clone the repository
# if you are using ssh
$ git clone git@github.com:Abooow/Paia.git
# if you are using https
$ git clone https://github.com/Abooow/Paia.git
Start by creating a new Console Application.
dotnet new console -o "APP_NAME"
Add the following lines of code in Program.cs
using Paia;
var builder = new AppBuilder()
builder.Build().Run<MyFirstView>();
MyFirstView
will become the starting View for the application, we'll create that View in the next section.
To create a View, start by creating a new class and inherit the ViewBase
class.
using Paia.Views;
class MyFirstView : ViewBase
{
public override ViewResult Render()
{
Console.Clear();
Console.WriteLine("Hello World!");
Console.WriteLine();
Console.WriteLine("Press 1 to exit");
char input = Console.ReadKey().KeyChar;
return input switch
{
'1' => Exit(),
_ => ReRenderView()
};
}
}
The Render()
method is where you place your main/rendering logic. The method returns a ViewResult
, which tells the program what to do next after finishing the rendering process.
Exit()
will return a ViewResult telling the framework to exit the application with exitcode 0. (Read more about Exit() and exitcode here)
ReRenderView()
instructs the framework to remain in the current view but refresh its display. The state of the View will NOT change, the ViewManager will keep the same instance of the View and only call the Render method again. If you want to refresh the view without retaining its current state, use the RefreshView()
method instead.
To change view, simply use the ChangeView<TView>()
method provided by the ViewBase class.
using Paia.Views;
class MyFirstView : ViewBase
{
public override ViewResult Render()
{
Console.Clear();
Console.WriteLine("Hello World!");
Console.WriteLine();
Console.WriteLine("Press 1 to change View, 2 to exit");
char input = Console.ReadKey().KeyChar;
return input switch
{
'1' => ChangeView<MySecondView>(),
'2' => Exit(),
_ => ReRenderView()
};
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class MySecondView : ViewBase
{
public override ViewResult Render()
{
Console.Clear();
Console.WriteLine("Hello World from my Second View!");
Console.WriteLine();
Console.WriteLine("Press a key to go back...");
Console.ReadKey();
return GoBack();
}
}
When changing to a new View, the old View (MyFirstView) will be pushed to a stack called BackStack by the ViewManager, making it possible to return to it later if needed.
The GoBack()
method pops the stack and renders the previous View (MyFirstView), simultaneously, the current view (MySecondView) is added to another stack called FrontStack. This enables you to move forward in the application flow. You can do this by calling the GoForward()
method.
Let's add a public Name
property to MySecondView
. Now MyFirstView
will be able to assign a value to it before changing view.
class MySecondView : ViewBase
{
public string Name { get; set; }
public override ViewResult Render()
{
Console.Clear();
Console.WriteLine("Hello World from my Second View!");
Console.WriteLine($"And hello to you, {Name}!");
Console.WriteLine();
Console.WriteLine("Press a key to go back...");
Console.ReadKey();
return GoBack();
}
}
class MyFirstView : ViewBase
{
public override ViewResult Render()
{
Console.Clear();
Console.WriteLine("Hello World!");
Console.WriteLine();
Console.WriteLine("Press 1 to change View, 2 to exit");
char input = Console.ReadKey().KeyChar;
return input switch
{
'1' => ChangeView<MySecondView>(view => view.Name = "Monkey Paia"),
'2' => Exit(),
_ => ReRenderView()
};
}
}
Returning to MyFirstView
, the ChangeView<MySecondView>()
method accepts an Action<MySecondView>
to be passed as a argument.
In the provided example, a lambda expression is used where view
serves as a reference to a MySecondView instance. This is how we can access the Name
property in order to assign a value to it.
Let's say we want to be able to change the welcome message in the starting view from Main()
.
Start by adding a public property called Message
in MyFirstView
.
class MyFirstView : ViewBase
{
public string Message { get; set; }
public override void OnInitialized()
{
Message = "Hello World!";
}
public override ViewResult Render()
{
Console.Clear();
Console.WriteLine(Message);
Console.WriteLine();
Console.WriteLine("Press 1 to change View, 2 to exit");
char input = Console.ReadKey().KeyChar;
return input switch
{
'1' => ChangeView<MySecondView>(view => view.Name = "Monkey Paia"),
'2' => Exit(),
_ => ReRenderView()
};
}
}
The OnInitialized()
method will be called only once per View instance, immediately after the constructor and right before the Render()
method. Place your initialization code in the OnInitialized()
method.
Passing data to the starting View is done in a similar manner as the previous section, by passing a Action<MyFirstView>
as an argument, but to the .Run<MyFirstView>()
method instead.
var builder = new AppBuilder()
builder.Build().Run<MyFirstView>(view => view.Message = "Yo World!");
Add services to the app by using the builder.Services
property in AppBuilder
.
var builder = new AppBuilder()
builder.Services.AddSingleton<IMyService, MyServiceImplementation>()
builder.Build().Run<MyFirstView>(view => view.Message = "Yo World!");
To inject a service to a view, use the [Inject]
attribute on a public property with a setter.
using Paia.Attributes;
class MyFirstView : ViewBase
{
[Inject]
public IMyService MyService { get; set; }
public override ViewResult Render()
{
...
}
}
To exit the application with a exitcode other than 0, you need a return statement on the .Run<>()
method.
var builder = new AppBuilder()
return builder.Build().Run<MyFirstView>();
The .Run<>()
method returns an int, which is the exit code for the application.
Exit()
(called from Views) will return 0 by default, but has a overload allowing you to pass an integer as a argument for a custom exitcode.
class MyFirstView : ViewBase
{
public override ViewResult Render()
{
Console.WriteLine("Press a key for a nice exit...");
Console.ReadKey();
return 69;
}
}
It's possible to also return an integer directly from a View, there is an implicit conversion from int to ViewResult. This is telling the View to exit with exitcode 69.
This repository is currently maintained by @Abooow.
This project has been released under the MIT license. More information can be found by viewing the license here.