Html.Forms
License: MIT
Target framework: .NET Core 3.1+ or .NET 5+
Development status: Beta
Framework for developing desktop applications with HTML GUI in .NET. Html.Forms app is .NET console application that hosts a minimal HTTP server and serves HTML pages on a local endpoint. User interacts with the app using any browser. Html.Forms uses HTML markup with minimal syntax extensions to define GUI and codebehind in C# or other .NET language to define logic. Apps run on any operating system supported by .NET.
Creating minimal app
Create new .NET Core/.NET console application project. Add index.html file that defines main page UI:
<html>
<head>
<title>Html.Forms sample</title>
</head>
<body>
<form method="post">
<h2>HTML Forms sample</h2>
<p>Name: <input type="text" name="name" /></p>
<p>Location: <input type="text" name="location" /></p>
<p><input type="submit"/></p>
<p><textarea readonly name="output"></textarea></p>
</form>
</body>
</html>
Include index.html file as embedded resource in .csproj:
<ItemGroup>
<None Remove="index.html" />
<EmbeddedResource Include="index.html" />
</ItemGroup>
Add IndexPage class that defines main page codebehind:
using System;
using Html.Forms;
namespace HtmlFormsSample
{
class IndexPage : Page
{
public IndexPage()
{
this.FileName = "index.html";
this.Html = ReadFromResource(this.FileName);
}
protected override void OnLoad(LoadEventArgs args)
{
if (!this.HasField("name")) return;
string name = this.GetFieldAs<string>("name");
string location = this.GetFieldAs<string>("location");
string output = "Hello, " + name + " from " + location + "!";
this.SetField("output", output);
}
}
}
Modify Program.cs file to include framework startup code:
using System;
using Html.Forms;
namespace HtmlFormsSample
{
class Program
{
static void Main()
{
Application app = new Application();
using (app)
{
app.Name = "HtmlFormsSample";
app.AddPages(typeof(Program).Assembly);
app.RunInBackground();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
Console.WriteLine("Application exited.");
}
}
}
Now you can build and run the created app. Application.RunInBackground will attempt to automatically open HomepageUrl in default system browser, if it fails, you need to open browser manually. The example app demonstrates using the standard HTML Submit button to submit values of two text input fields and invoke Page.OnLoad method in codebehind class. The implementation of OnLoad reads submitted field values, produces output string and returns it to user as a value of <textarea>
element.
Basic concepts
Html.Forms application is defined by creating an instance of the Html.Forms.Application class and adding one or more pages to it. Application renders pages on some local HTTP endpoint, by default it’s http://localhost:(port)/htmlforms/
.
Page consists of the HTML file with UI definition and codebehind class derived from Html.Forms.Page. Page markup must include a single <form>
element with POST method inside its body, and the contents of page UI must be placed inside that element. You can compose page UI from standard HTML elements and Html.Forms controls.
Supported HTML elements
HTML elements are defined statically in markup. Some elements, such as <h1>
, are always rendered by framework in their unmodified form. Others, mainly <input>
elements, are modified by markup rewriter to reflect values programmatically set from codebehind via Page.SetField method. The following elements are processed by rewriter:
<input type="text"/>
<input type="checkbox"/>
<input type="radio"/>
<textarea>
<select>
and<option>
<div name="...">
<div>
elements are only processed by rewriter if they have name attribute set and the form contains a value with the same name. Such elements are called dynamic blocks. The content of dynamic blocks, unlike for other elements, is not HTML-encoded before output. This enables inserting a dynamically generated HTML fragment into the rendered page.
Controls
Control is an object placed on a page that can dynamically render HTML using some logic defined in .NET code. Control classes inherit from Html.Forms.Control.
To use a control, put <dn-control>
element into the page markup, setting its id attribute into some unique string. Then, in the constructor of the page class, create an instance of the control object, set its id to the same string as id attribute, and add it into the page using Page.AddControl method. The markup rewriter will replace the <dn-control>
element with control’s rendered markup when processing the page.
The following standard controls are provided in Html.Forms.Controls namespace:
- ClockControl: displays current date and time
- ComboBox: provides a drop-down list (
<select>
/<option>
element) where list elements are dynamically defined in codebehind - ContainerControl: renders inner HTML wrapped in block element (mainly useful to programmatically show/hide content)
- DataGridView: enables user to edit tabular data
- DropDownPanel: shows/hides content when user clicks on the hyperlink
- NavigationPanel: renders a collection of hyperlinks defined dynamically in codebehind
- ListView: renders a collection of items
- PictureBox: displays an image specified programmatically in codebehind
- PropertyGrid: enables user to edit object properties
- TabControl: enables switching between multiple tab pages by clicking on tab titles
This project uses Fugue Icons 3.5.6, (C) 2021 Yusuke Kamiyamane, Creative Commons Attribution 3.0 License.