TinyChat.DevExpress 2.2.9

There is a newer version of this package available.
See the version list below for details.
dotnet add package TinyChat.DevExpress --version 2.2.9
                    
NuGet\Install-Package TinyChat.DevExpress -Version 2.2.9
                    
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="TinyChat.DevExpress" Version="2.2.9" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TinyChat.DevExpress" Version="2.2.9" />
                    
Directory.Packages.props
<PackageReference Include="TinyChat.DevExpress" />
                    
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 TinyChat.DevExpress --version 2.2.9
                    
#r "nuget: TinyChat.DevExpress, 2.2.9"
                    
#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 TinyChat.DevExpress@2.2.9
                    
#: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=TinyChat.DevExpress&version=2.2.9
                    
Install as a Cake Addin
#tool nuget:?package=TinyChat.DevExpress&version=2.2.9
                    
Install as a Cake Tool

NuGet Status

TinyChat 💬

A minimalistic but extensible chat control library for Windows Forms.

Screenshot

✨ Features

  • Two control suites: vendor-control-free Windows Forms controls in TinyChat and a skinnable DevExpress implementation in TinyChat.DevExpress
  • Streaming support: real-time message streaming for AI assistants and live conversations
  • Microsoft.Extensions.AI integration: use any registered IChatClient, including keyed services, with streaming, cancellation, chat options, reasoning, and function calls
  • File and image attachments: add files through drag and drop, clipboard paste, or the public API; images are shown as previews
  • Selectable and copyable content: directly select regular message text, function-call arguments and results, or reasoning details and copy it with standard keyboard shortcuts
  • Designer-friendly appearance: configure fonts, colors, history, message and input spacing, welcome alignment, the splitter, and behavioral options in the Windows Forms Designer
  • New-chat lifecycle: cancel the active response and clear the conversation and input draft in one call
  • Readable message rendering: native controls use cleaned plain text, while the DevExpress suite keeps its safe HTML/CSS formatting in a permanently selectable message surface
  • Extensible architecture: interface-driven design and factory methods for custom message types and UI components

Control suites

NuGet package Control UI components Default formatter
TinyChat ChatControl Native Windows Forms controls PlainTextMessageFormatter
TinyChat.DevExpress DXChatControl DevExpress controls SimplifiedHtmlMessageFormatter (selectable HTML/CSS body view)

Both controls share the same public chat API. DXChatControl derives from ChatControl and replaces the primary editors, message controls, history, welcome surface, and splitter with DevExpress counterparts. TinyChat.DevExpress is built and tested with DevExpress 24.2.12 and requires the corresponding DevExpress license.

💖 Motivation

While there are countless web-based chat controls, there are very few for the good old Windows Forms ecosystem. TinyChat provides a focused user interface for interacting with AI models inside an existing WinForms application.

DevExpress also offers a feature-rich AI Chat Control. It is based on web technologies and therefore adds a significant set of deployment dependencies. TinyChat deliberately stays smaller and exposes factory methods and interfaces for applications that need to customize it.

Known limitations

  • Full formatting specifications are not implemented. Native Windows Forms message controls display cleaned plain text. The DevExpress controls support a practical subset of common HTML and Markdown constructs, but not every HTML, Markdown, or RTF feature an assistant may emit.
  • Image rendering currently focuses on attachments. Local or pasted images have previews and are sent to compatible IChatClient implementations as multimodal content. Arbitrary remote images or image content returned by an assistant are not rendered automatically.
  • Provider capabilities still apply. A provider or model may reject a binary attachment format even though TinyChat can load and forward it. Override ConvertFileAttachment() when files need extraction, upload, or RAG processing first.

🚀 Quick start

Native Windows Forms

using TinyChat;

var chatControl = new ChatControl
{
    Dock = DockStyle.Fill
};
Controls.Add(chatControl);

For the DevExpress suite, reference TinyChat.DevExpress and instantiate DXChatControl instead. The remaining API is the same.

Basic message handling

The Messages property supplies an existing conversation. MessageSending can inspect or cancel a user message, while MessageSent runs after it was accepted.

chatControl.MessageSent += (_, e) =>
{
    Console.WriteLine($"User sent: {e.Content}");

    chatControl.AddMessage(
        new NamedSender("Assistant"),
        new StringMessageContent("Hello! How can I help you?"));
};

Starting a new chat

Use StartNewChat() instead of assigning an empty message collection. It requests cancellation of an active response and clears the built-in conversation, text draft, pending attachments, and selection in one call.

chatControl.NewChatStarted += (_, _) =>
{
    // Reset any application-specific session state here.
};

chatControl.StartNewChat();

Custom input controls can implement IChatInputDraftControl so their own draft state is cleared by the same call.

Designer and appearance settings

The following properties are available in the Windows Forms Designer and work for both control suites:

chatControl.MessageFont = new Font("Segoe UI", 10f);
chatControl.InputFont = new Font("Segoe UI", 10f);
chatControl.InputEditorBackColor = Color.Empty; // native/skin default
chatControl.InputEditorForeColor = Color.Empty; // native/skin default
chatControl.InputEditorBorderStyle = BorderStyle.Fixed3D;
chatControl.InputPlaceholderText = "Ask TinyChat";
chatControl.WelcomeFont = new Font("Segoe UI", 14f);
chatControl.WelcomeMessage = "How can I help?";
chatControl.HistoryPadding = new Padding(12);
chatControl.MessagePadding = new Padding(10);
chatControl.MessageMargin = new Padding(4);
chatControl.InputPadding = new Padding(10);
chatControl.WelcomeTextAlign = ContentAlignment.MiddleCenter;
chatControl.IsSplitterFixed = true;
chatControl.SplitterPosition = 90;
chatControl.AllowExpandFunctionCalls = true;
chatControl.AllowExpandReasoning = true;
chatControl.IncludeFunctionCalls = false;
chatControl.IncludeReasoning = false;
chatControl.AssistantSenderName = "AI Assistant";

Font, ForeColor, and BackColor provide the global appearance for the chat surface and are propagated by both the native Windows Forms and DevExpress suites. The editable input surface deliberately keeps its native Windows or active DevExpress skin colours so that it remains visually distinct and does not look read-only. Set InputEditorBackColor or InputEditorForeColor to override those defaults; reset either property to Color.Empty to resume platform/skin rendering. MessageFont and InputFont inherit from Font until explicitly changed; resetting them resumes that inheritance. WelcomeFont is independent, and resetting it restores the larger default welcome font.

The layout and input appearance properties have the same meaning and defaults in both suites:

Property Scope Default after reset
HistoryPadding Padding inside the history area, including the welcome surface 0 on every side
MessagePadding Inner padding of regular, function-call, and reasoning messages 8 on every side
MessageMargin Outer margin of every message 3 on every side
InputPadding Inner padding of the complete input area 8 on every side
InputEditorBackColor Background of the editable text surface Color.Empty (platform/skin default)
InputEditorForeColor Text colour of the editable text surface Color.Empty (platform/skin default)
InputEditorBorderStyle Native border or mapped DevExpress skin border BorderStyle.Fixed3D
InputPlaceholderText Prompt shown while the input is empty Empty
WelcomeTextAlign Alignment of the welcome text within the history area ContentAlignment.MiddleCenter
IsSplitterFixed Prevents the user from moving the splitter when enabled false
SplitterPosition Height of the lower input area in pixels 60
AllowExpandFunctionCalls Allows function-call details to be expanded true
AllowExpandReasoning Allows reasoning details to be expanded true
IncludeFunctionCalls Shows function calls captured from IChatClient responses false
IncludeReasoning Shows reasoning captured from IChatClient responses false
AssistantSenderName Name shown for automatic IChatClient responses Assistant

Resetting one of these properties in the Designer restores the listed value. The inherited ChatControl.Padding property remains the outer padding around the combined chat surface; it is not inherited by the history, messages, or input area.

These settings also apply retrospectively. Changing the assistant name, formatter, content filters, or expand permissions updates the existing message controls in place instead of rebuilding the history. Hidden function calls and reasoning continue to be captured, so enabling their filters later reveals the original controls without interrupting active streaming. Hiding a selected message intentionally clears that selection. Messages added explicitly through AddMessage keep their own sender identity and remain visible independently of the IChatClient visualization filters.

Selecting and copying text

Both control suites display regular message bodies permanently in selectable text views. Drag directly over the required text and press <kbd>Ctrl</kbd>+<kbd>C</kbd>; no renderer or selection-mode switch is required. Starting a selection in another message clears the previous selection, so multiple message bodies are never highlighted at the same time.

Function-call arguments and results as well as reasoning details are directly selectable in the same way. You can also click the sender/header or message background and press <kbd>Ctrl</kbd>+<kbd>C</kbd> to copy the complete message.

File and image attachments

When AllowFileAttachments is enabled (the default), users can:

  • drop files anywhere on the chat;
  • paste copied files or a bitmap into the input;
  • remove attachments from the draft before sending;
  • see small image previews and document tiles.

The default per-file limit is 20 MiB and can be changed with MaximumAttachmentFileSize. Files can also be supplied in code:

await chatControl.AddFilesToInputAsync(openFileDialog.FileNames);

await chatControl.SendFilesAsync(
    ["report.pdf", "diagram.png"],
    "Summarize these files.");

Text attachments are forwarded as named text sections. Images and other binary files are represented as typed DataContent for Microsoft.Extensions.AI.

Streaming messages with IAsyncEnumerable

Pass a token stream to AddStreamingMessage(). TinyChat marshals display updates back to the UI synchronization context.

IAsyncEnumerable<string> stream = GetTokenStream();
chatControl.AddStreamingMessage(new NamedSender("AI Assistant"), stream);

Using IChatClient with dependency injection

TinyChat can resolve and call a Microsoft.Extensions.AI.IChatClient automatically.

using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using TinyChat;

var services = new ServiceCollection();
services.AddSingleton<IChatClient>(CreateChatClient());

var chatControl = new ChatControl
{
    ServiceProvider = services.BuildServiceProvider(),
    UseStreaming = true,
    AssistantSenderName = "AI Assistant"
};

The complete conversation is converted and passed to the client. Override ConvertToChatMessages() or DetermineChatRole() when the default sender-to-role mapping does not fit your application. ChatOptions and ChatOptionsRequested customize each request; IncludeFunctionCalls and IncludeReasoning control whether the corresponding captured response details are visible.

Keyed clients are supported as well:

services.AddKeyedSingleton<IChatClient>("basic", CreateBasicClient());
services.AddKeyedSingleton<IChatClient>("premium", CreatePremiumClient());

chatControl.ChatClientServiceKey = "premium";

Formatting

Both suites use a permanently visible message surface so that text can always be selected without changing renderers. ChatControl uses a read-only native TextBox and PlainTextMessageFormatter to remove common HTML and Markdown syntax while keeping the text readable.

DXChatControl uses a permanent DevExpress HtmlContentControl. It combines formatted rendering with native DevExpress text selection, automatic height calculation, and stable streaming updates in the same control. SimplifiedHtmlMessageFormatter remains the default; its supported bold, italic, underline, strike-through, heading, color, code-font, paragraph, line-break, and link output is converted to a safe HTML/CSS-template subset before rendering. Remote images and unsafe link schemes are not injected into message templates.

Both suites preserve Unicode emoji, including multi-code-point sequences. Their exact colour and glyph style still depend on the installed Windows fonts and the active renderer; native Windows Forms commonly displays monochrome glyphs.

Function-call arguments and results as well as reasoning details use the same selectable DevExpress HTML surface, with their plain text HTML-encoded before display.

To customize normalization and rendering, implement IMessageFormatter and override CreateDefaultMessageFormatter().

🎬 Demos

DemoApp contains both native Windows Forms and DevExpress examples, including direct IChatClient integration:

dotnet run --project DemoApp

Credits

The package icon was made by Vectors Market and is licensed under the Flaticon license.

Product Compatible and additional computed target framework versions.
.NET net9.0-windows7.0 is compatible.  net10.0-windows was computed.  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.2.11 37 10/27/2026
2.2.10 37 10/27/2026
2.2.9 87 10/26/2026
2.2.8 225 7/15/2026
2.2.7 135 6/12/2026
2.2.6 137 5/5/2026
2.2.5 133 4/23/2026
2.2.4 149 4/7/2026
2.2.3 133 4/7/2026
2.2.2 136 3/26/2026
2.2.1 124 3/20/2026
2.1.7 127 3/20/2026
2.1.6 134 3/20/2026
2.1.5 148 3/4/2026
2.1.4 138 3/2/2026
2.1.3 138 3/2/2026
2.1.2 146 3/2/2026
2.1.1 144 2/26/2026
2.0.10 148 2/24/2026
2.0.9 142 2/24/2026