OutWit.Common.Forms 1.2.0

dotnet add package OutWit.Common.Forms --version 1.2.0
                    
NuGet\Install-Package OutWit.Common.Forms -Version 1.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="OutWit.Common.Forms" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OutWit.Common.Forms" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="OutWit.Common.Forms" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add OutWit.Common.Forms --version 1.2.0
                    
#r "nuget: OutWit.Common.Forms, 1.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package OutWit.Common.Forms@1.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=OutWit.Common.Forms&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=OutWit.Common.Forms&version=1.2.0
                    
Install as a Cake Tool

OutWit.Common.Forms

A form described as data: groups, tabs, fields, options and the conditions that decide what is live. Serialisable, transferable, and enough for anybody to draw the form and keep it consistent while somebody types.

Nothing here knows what a field means. That is the point: a plugin can contribute a screen without shipping controls, and a second front end — a browser, a remote console, a different toolkit — becomes a renderer rather than a rewrite.

Contents

Model (OutWit.Common.Forms.Model)

  • FormSchema — the form: a key, a title key, a version, its groups, and the shape they flow into (Columns, ColumnWeights, Flow)
  • FormGroup — a heading with things under it. A Section; a strip of Tabs and the Tabs in it; or a List and the Entrys in it — each named, summarised by a SummaryKey, and marked on by ActiveWhen or by its switch. Optionally a SwitchKey naming the boolean drawn as the group's own on/off; Columns, ColumnWeights and Span for shape
  • FormField — a key, a kind, bounds, a unit or a quantity, options, a default, a span; whether it is read-only, optional, or a mirror of a field declared elsewhere; and when it is enabled or visible
  • FormFieldKindText, Label, Number, Duration, Boolean, Choice, MultiChoice, Range, Date, Quantity, Tokens. Eleven, and a kind exists only where it changes what a renderer has to do
  • FormOption — an answer a field offers, with its own visibility
  • FormCondition — a comparison against another field's value, or a tree of them
  • FormValues / FormValue — what is currently in the form, and where each value came from (Set, Default, Read, Estimated, NotRead, NotAvailable)
  • FormValidation / FormIssue — what the authority says about the whole of it
  • FormPlacement<T> — where a field or a group ended up: row, column, span. Worked out by whoever draws, never serialised

Contract (OutWit.Common.Forms.Interfaces)

  • IFormValidator — whoever declared the form, answering what the values mean together

Evaluation (OutWit.Common.Forms.Utils)

  • FormConditionExtensionsIsMet, IsEnabled, IsVisible, IsActive: answered locally, on every change, without asking anybody
  • FormSchemaExtensions — walking the tree, plus DuplicateKeys() and UnknownKeys() for the structural mistakes that are otherwise invisible: two fields under one key, a condition on a field nobody declared, a group switched by a field it does not hold
  • FormLayoutExtensionsPlacements(), Stacked(), Weights(): the arithmetic that turns columns and spans into rows, kept here so that two renderers affording the same number of columns lay the same form out the same way

The line it draws

Structure — what exists, and what is live while what else is set — is in the schema and is evaluated where the form is drawn. A round trip to decide whether a control is greyed makes a form feel broken.

Meaning — which combinations are acceptable, which limit depends on which other value — is the authority's, asked through IFormValidator after a change. Copying that into a renderer is how two implementations of one rule come to disagree.

Shape, not measurement

Columns, Span, ColumnWeights and Flow are the only things here about arrangement, and they say shape: that these answers are short enough to sit beside each other, which of them wants more room, which way the sections fill the page. Not how wide anything is — the form does not know whether it is being drawn in a popup, a page or a phone. A renderer with no room uses fewer columns, and one column is always a correct answer.

Serialisation

MemoryPack, natively: [MemoryPackable] with explicit [MemoryPackOrder], so a schema crosses a WitRPC boundary with nothing configured at either end.

No other format's attributes, deliberately — a model carrying them has made a private arrangement with one serialiser. For a product standardised on MessagePack there is OutWit.Common.Forms.MessagePack: one call, scoped to this model alone.

Example

var schema = new FormSchema("Recorder.Settings", "Forms.Title")
{
    Groups =
    {
        new FormGroup("Recording", "Forms.Recording")
        {
            Fields =
            {
                new FormField("RecordTime", "Forms.RecordTime", FormFieldKind.Choice)
                {
                    DefaultValue = "Time24",
                    Options =
                    {
                        new FormOption("Time24", "Forms.Time24"),
                        new FormOption("Time48", "Forms.Time48")
                    }
                },
                new FormField("Diary", "Forms.Diary", FormFieldKind.Boolean) { DefaultValue = "false" },
                new FormField("Diary.Kind", "Forms.Diary.Kind", FormFieldKind.Choice)
                {
                    EnabledWhen = FormCondition.On("Diary", FormOperator.IsTrue)
                }
            }
        }
    }
};

var values = FormValues.Of(schema);          // complete, at the defaults

values.Set("Diary", "true");

schema.Field("Diary.Kind")!.IsEnabled(values);   // true, decided locally

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on OutWit.Common.Forms:

Package Downloads
OutWit.Common.Forms.MessagePack

Carries OutWit.Common.Forms on a MessagePack wire: one registration, scoped to the form model alone, so a product standardised on MessagePack can send a schema without loosening how anything else of its own is serialised.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.0 140 9/9/2026