A minimalistic but extensible chat control library for Windows Forms.
- Simplistic Chat Interface: Clean, responsive chat UI with message history and input controls
- Streaming Support: Real-time message streaming for AI assistants and live conversations
- Basic formatting support: Supports cleaning HTML and Markdown formatting for WinForms controls and basic HTML and Markdown support for DevExpress controls
- Extensible Architecture: Interface-driven design allowing custom message types and custom UI components
- Made for WinForms: Because business applications might need AI chats, too
While there are countless web-based chat controls, there's nearly to none for the good old Windows Forms ecosystem and this is not surprising. However, I needed a very basic user interface to interact with AI models within an WinForms application.
DevExpress, the component vendor of my choice, has a very nice chat control. However, it's built upon web technologies and with that it introduces a significant number of dependencies to ship. I didn't want to pack additional 50MB of assemblies for a single control and theirs is so feature-rich that I would have to to disable 90% of it's functionality nevertheless.
That's why I quickly hacked down TinyChat. I hope this might help anyone out there. But please keep in mind that I never inteded to build a full-featured chat client with advanced text formatting support and so on. If you need more features, please consider sending pull-requests or using the DevExpress chat control.
These features are not implemented and I don't plan to implement them. However, I'd be happy to review pull-requests.
- Full formatting support
Basic formatting is supported since v2.0 but full formatting spec support will be very hard to do in Winforms. Especially because AI assistants can come up with pretty much every flavor of formatting like HTML, Markdown, RTF, etc.
- File attachment support
- Image support
- everything else you know from chatbots
- Designer support for properties like UI settings like Fonts, Splitter position, ...
- Select and copy texts
- Starting new chats
The chat control provides a Messages property that can be set to provide message history.
When the user is sending messages, the events MessageSending and MessageSent gets fired to prevent or react on user messages.
using TinyChat;
var chatControl = new ChatControl();
chatControl.Dock = DockStyle.Fill;
Controls.Add(chatControl);
// Set up message handling
chatControl.MessageSent += (sender, e) =>
{
// Handle user messages
Console.WriteLine($"User sent: {e.Content}");
// Add a response
chatControl.AddMessage(
new NamedSender("Assistant"),
new StringMessageContent("Hello! How can I help you?")
);
};Use AddStreamingMessage() to pass in a stream of tokens asynchronously. The chat component will take care of updating the user interface from background threads.
IAsyncEnumerable<string> stream = ...;
chatControl.AddStreamingMessage(new NamedSender("AI Assistant"), stream);TinyChat now supports direct integration with Microsoft.Extensions.AI.IChatClient, enabling automatic AI responses with minimal boilerplate code.
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using TinyChat;
// Set up dependency injection
var services = new ServiceCollection();
// Register your IChatClient implementation (e.g., OpenAI, Azure OpenAI, Ollama, etc.)
services.AddSingleton<IChatClient>(/* your IChatClient implementation */);
var serviceProvider = services.BuildServiceProvider();
// Configure the ChatControl
var chatControl = new ChatControl
{
ServiceProvider = serviceProvider,
UseStreaming = true, // Enable streaming (default)
AssistantSenderName = "AI Assistant"
};
// That's it! The ChatControl will automatically call IChatClient when users send messages
// The entire conversation history is passed to the IChatClientKey Features:
- Automatic Integration: No need to manually handle
MessageSentevents - Conversation History: Full message history is automatically passed to the IChatClient
- Streaming Support: Toggle between streaming and non-streaming responses
- Keyed Services: Support for keyed service resolution via
ChatClientServiceKeyproperty - Cancellation Support: Long-running operations can be cancelled
- Extensible: Override
ConvertToChatMessages()orDetermineChatRole()for custom behavior
Using Keyed Services:
// Register multiple IChatClient instances with different keys
services.AddKeyedSingleton<IChatClient>("basic", /* basic model */);
services.AddKeyedSingleton<IChatClient>("premium", /* premium model */);
// Use a specific keyed service
chatControl.ChatClientServiceKey = "premium";WinForms controls don't support partial text formatting. To make the WinForms ChatControl usable with AI chatbots, TinyChat will try to remove basic HTML and Markdown formatting.
The DevExpress Demo goes even further and makes use of the basic HTML support with DevExpress controls and tries to turn HTML or even Markdown input into these basic HTML tags. Tags that are not supported are stripped out to keep the text readable.
It's possible to create a custom formatter by implementing IMessageFormatter and instantiating it by overriding ChatControl.CreateDefaultMessageFormatter().
The repository includes multiple demo applications:
- WinFormsDemo: A basic Windows Forms application with dependency-free standard controls
- WinFormsDemo with IChatClient: Shows automatic IChatClient integration (run with
--ichatclientflag) - DevExpressDemo: Showcases the customizability with skinned DevExpress components (requires a DevExpress license)
dotnet run --project WinFormsDemo # Basic demo
dotnet run --project WinFormsDemo -- --ichatclient # IChatClient integration demo
dotnet run --project DevExpressDemoThe package icon was made by Vectors Market and is licensed by the Flaticons license.

