Oakrey.Applications.Terminals 2.0.3

dotnet add package Oakrey.Applications.Terminals --version 2.0.3
                    
NuGet\Install-Package Oakrey.Applications.Terminals -Version 2.0.3
                    
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="Oakrey.Applications.Terminals" Version="2.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Oakrey.Applications.Terminals" Version="2.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Oakrey.Applications.Terminals" />
                    
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 Oakrey.Applications.Terminals --version 2.0.3
                    
#r "nuget: Oakrey.Applications.Terminals, 2.0.3"
                    
#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 Oakrey.Applications.Terminals@2.0.3
                    
#: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=Oakrey.Applications.Terminals&version=2.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Oakrey.Applications.Terminals&version=2.0.3
                    
Install as a Cake Tool

Oakrey.Applications.Terminals

A .NET 10 WPF library for building terminal-like interfaces in MVVM applications. It provides command history, message management, reactive updates, file export, and built-in integration with Oakrey.Log and Oakrey.Telemetry.

Main features

  • Command history - navigable history of submitted commands with duplicate deduplication and a configurable capacity (default 20 entries).
  • Generic message collection - IMessageCollection<TMessage> backed by a ReplaySubject for reactive change notifications.
  • Built-in message types - StringMessage and StringAndDirectionMessage (with Direction) ship out of the box; custom types require only implementing IMessage.
  • Sorting and display settings - IMessageViewSettings controls sort order (OldestOnTop / NewestOnTop), displayed message count, and timestamp visibility.
  • File export - SaveToFile command writes messages to a .txt file via a standard save dialog with a configurable file name prefix.
  • Context menu integration - ContextCommands collection is data-bindable and ships with "Clear" and "Save to file" entries.
  • Logging and telemetry - all commands and file operations are traced through Oakrey.Log and Oakrey.Telemetry automatically.

Architecture

classDiagram
    class IMessage {
        +DateTime Timestamp
    }
    class StringMessage {
        +string Message
        +DateTime Timestamp
    }
    class StringAndDirectionMessage {
        +string Message
        +Direction Direction
        +DateTime Timestamp
    }
    class IMessageCollection~TMessage~ {
        +List~TMessage~ Messages
        +AddMessage(TMessage)
        +ClearMessages()
        +Subscribe(IObserver)
    }
    class MessageCollection~TMessage~
    class IMessageViewSettings {
        +SortOrder SortOrder
        +int DisplayedMessages
        +bool ShowTimestamp
    }
    class HistoryViewModel {
        +string Command
        +IStringHistoryProvider History
        +AddCommandToHistory()
        +HistoryUp()
        +HistoryDown()
        +Export() string
    }
    class TerminalViewModel~TMessage~ {
        +ObservableCollection~TMessage~ Messages
        +ObservableCollection~TMessage~ TerminalMessages
        +ObservableCollection~ContextMenuForViewModel~ ContextCommands
        +ICommand SendCommand
        +ICommand ClearMessages
        +ICommand SaveToFile
        #DefaultCommand()*
        #TraceLine(TMessage)*
        +string FilePrefix*
    }

    IMessage <|.. StringMessage
    IMessage <|.. StringAndDirectionMessage
    IMessageCollection <|.. MessageCollection
    HistoryViewModel <|-- TerminalViewModel
    TerminalViewModel o-- IMessageCollection
    TerminalViewModel o-- IMessageViewSettings

Key types

Type Description
IMessage Minimal contract for a timestamped message.
StringMessage Simple string message with a DateTime timestamp.
StringAndDirectionMessage Message with an additional Direction (e.g. inbound/outbound).
MessageCollection<TMessage> Default in-memory IMessageCollection<TMessage> using System.Reactive.
IMessageViewSettings / MessageViewSettings Controls sort order, display count, and timestamp visibility.
IStringHistoryProvider / CommandHistory Navigable, deduplicated command history (capacity 20).
HistoryViewModel WPF ViewModel base with command input and history navigation.
TerminalViewModel<TMessage> Abstract ViewModel base combining history, messages, export, and context menu.
ContextMenuForViewModel Bindable context menu entry pairing a display name with an ICommand.

Requirements

  • .NET 10 (Windows)
  • WPF (Windows Presentation Foundation)

Installation

NuGet Package Manager

Search for Oakrey.Applications.Terminals in Visual Studio under Tools > NuGet Package Manager > Manage NuGet Packages for Solution.

.NET CLI

dotnet add package Oakrey.Applications.Terminals

Package Manager Console

Install-Package Oakrey.Applications.Terminals

Configuration

Inject or create an IMessageViewSettings instance and pass it to your TerminalViewModel subclass:

MessageViewSettings settings = new()
{
    SortOrder = SortOrder.NewestOnTop,
    DisplayedMessages = 200,
    ShowTimestamp = true
};

Example usage

Implement TerminalViewModel<TMessage> to create a concrete terminal:

public sealed class MyTerminalViewModel : TerminalViewModel<StringMessage>
{
    public override string FilePrefix => "my-terminal";

    protected override string TraceLine(StringMessage message)
        => $"[{message.Timestamp:HH:mm:ss}] {message.Message}";

    protected override void DefaultCommand()
    {
        if (string.IsNullOrWhiteSpace(Command))
        {
            return;
        }
        devices.AddMessage(new StringMessage(Command));
    }
}

Bind in XAML:

<ItemsControl ItemsSource="{Binding TerminalMessages}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Message}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

<TextBox Text="{Binding Command, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="Send" Command="{Binding SendCommand}" />
<ContextMenu ItemsSource="{Binding ContextCommands}">
    <ContextMenu.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="Header" Value="{Binding DisplayName}" />
            <Setter Property="Command" Value="{Binding MessageContextMenuCommand}" />
        </Style>
    </ContextMenu.ItemContainerStyle>
</ContextMenu>

Development notes

  • TerminalViewModel<TMessage> implements IDisposable. Always dispose instances that are no longer needed to unsubscribe from the reactive pipeline.
  • CommandHistory capacity is fixed at 20 entries. Provide a custom IStringHistoryProvider to change this behaviour.
  • MessageCollection<TMessage>.ClearMessages() calls messageSubject.OnNext(messages.Last()) after clearing; ensure the collection is non-empty before clearing or guard accordingly in derived code.
  • Logging uses Oakrey.Log.LoggerFactory and tracing uses Oakrey.Telemetry.TracingFactory, both resolved by the concrete Type of the ViewModel subclass.

License

MIT - Copyright (c) Oakrey 2016-2025. See LICENSE for details.

Product Compatible and additional computed target framework versions.
.NET net10.0-windows7.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.3 39 5/15/2026
2.0.2 116 3/13/2026
2.0.1 119 2/11/2026
2.0.0 446 11/18/2025
1.2.1 258 9/29/2025
1.2.0 257 9/4/2025
1.1.0 228 7/1/2025
1.0.0 324 4/17/2025