AI Chat Control
- 6 minutes to read
Note
The DevExpress AI Chat Control (AIChatControl
) can only be used in Windows Forms applications that target the .NET 8+ framework.
The AI Chat Control (AIChatControl
) allows you to incorporate an interactive, Copilot-inspired chat-based UI within your WinForms application. This control leverages BlazorWebView
to reuse the DevExpress Blazor AI Chat component (DxAIChat). To use the WinForms AI Chat Control you must have one of the following active subscriptions: Universal, DXperience, ASP.NET & Blazor.
Getting Started
1. Install DevExpress NuGet Packages
DevExpress.AIIntegration.WinForms.Chat
DevExpress.Win.Design
(enables design-time features for DevExpress UI controls)
2. Change Project SDK
Update the project SDK to Microsoft.NET.Sdk.Razor
:
<Project Sdk="Microsoft.NET.Sdk.Razor">
3. Register AI Client
The following code snippet registers the Azure OpenAI client:
using Microsoft.Extensions.AI;
using DevExpress.AIIntegration;
internal static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
IChatClient asChatClient = new Azure.AI.OpenAI.AzureOpenAIClient(new Uri(AzureOpenAIEndpoint),
new System.ClientModel.ApiKeyCredential(AzureOpenAIKey))
.AsChatClient("GPT4o");
AIExtensionsContainerDesktop.Default.RegisterChatClient(asChatClient);
Application.Run(new Form1());
}
static string AzureOpenAIEndpoint { get { return Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"); } }
static string AzureOpenAIKey { get { return Environment.GetEnvironmentVariable("AZURE_OPENAI_APIKEY"); } }
}
Tip
Read the following help topic for additional information: How to Register an AI Client.
4. Create AI Chat Control
Drop the AIChatControl
from the toolbox onto a Form.
Note
The AI Chat Control does not support design-time rendering.
The following code snippet creates the AIChatControl
with default settings:
using DevExpress.AIIntegration.WinForms.Chat;
public partial class Chat : XtraForm {
public Chat() {
InitializeComponent();
AIChatControl chat = new AIChatControl(){
Name = "aiChatControl1",
Dock = DockStyle.Fill
};
this.Controls.Add(chat);
}
}
Streaming
The AI Chat Control can display responses from the AI assistant as they are generated in a natural, conversational flow (rather than waiting for the entire message to complete before showing it to the user). Enable the UseStreaming
setting to activate streaming:
Play the following animation to see the result:
Markdown Message Rendering
- Set the
ContentFormat
property to Markdown to receive responses as Markdown. - Handle the
MarkdownConvert
event to convert markdown text into HTML and make responses more readable, structured, and visually appealing.
The following example enables Markdown message rendering. The example uses the Markdig Markdown processing library to convert Markdown text into HTML.
public Chat() {
InitializeComponent();
aiChatControl1.ContentFormat = DevExpress.AIIntegration.Blazor.Chat.ResponseContentFormat.Markdown
aiChatControl1.MarkdownConvert += AiChatControl1_MarkdownConvert
}
void AiChatControl1_MarkdownConvert(object sender, DevExpress.AIIntegration.Blazor.Chat.WebView.AIChatControlMarkdownConvertEventArgs e) {
e.HtmlText = (MarkupString)Markdown.ToHtml(e.MarkdownText);
}
The following screenshot shows the result:
Handle Chat Messages
To manually process messages sent to an AI service, handle the MessageSent
event. For example, you can manually call the AI client or service of choice and return its responses to the chat. The following example adds responses to user questions:
using DevExpress.AIIntegration.Blazor.Chat.WebView;
using Microsoft.Extensions.AI;
public Chat() {
InitializeComponent();
aiChatControl1.MessageSent += AiChatControl1_MessageSent;
}
async void AiChatControl1_MessageSent(object sender, AIChatControlMessageSentEventArgs e) {
await e.SendMessage($"Processed: {e.Content}", ChatRole.Assistant);
}
Save and Load Chat History
Use the following methods to manage chat history:
SaveMessages
– Returns anIEnumerable<ChatMessage>
collection of messages.LoadMessages
– Loads messages from the specifiedIEnumerable<ChatMessage>
collection to the AI Chat Control and refreshes the control.
The following example saves/loads chat history when the user clicks the Save/Load button:
public partial class Chat : XtraForm {
List<BlazorChatMessage> chatHistory;
public Chat() {
InitializeComponent();
buttonSave.Click += ButtonSave_Click;
buttonLoad.Click += ButtonLoad_Click;
}
void ButtonSave_Click(object sender, EventArgs e) {
chatHistory = (List<BlazorChatMessage>)aiChatControl1.SaveMessages();
}
void ButtonLoad_Click(object sender, EventArgs e) {
if(chatHistory != null)
aiChatControl1.LoadMessages(chatHistory);
}
}
Create an Assistant That Chats Using Your Own Data
When integrating the OpenAI Assistant, you can configure it to retain and reference a specific context (for example, a text file or a PDF document). By providing a supplementary document as a context source, the assistant is primed with background information. OpenAI automatically parses the document and searches through it to retrieve relevant content to better respond to user queries.
Install the
DevExpress.AIIntegration.OpenAI
NuGet package. Add the highlighted code to the Program.cs file to register the OpenAI Assistant service:static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); IChatClient asChatClient = new Azure.AI.OpenAI.AzureOpenAIClient(new Uri(AzureOpenAIEndpoint), new System.ClientModel.ApiKeyCredential(AzureOpenAIKey)) .AsChatClient("GPT4o"); AIExtensionsContainerDesktop.Default.RegisterChatClient(asChatClient); AIExtensionsContainerDesktop.Default.RegisterOpenAIAssistants(new AzureOpenAIClient(new Uri(azureOpenAIEndpoint), new System.ClientModel.ApiKeyCredential(azureOpenAIKey)), "Gpt4o"); Application.Run(new Chat()); }
Handle the
Initialized
event with an async handler. Call thee.SetupAssistantAsync
method to supply a file and a prompt to the Open AI Assistant:using System.IO; using DevExpress.AIIntegration.OpenAI.Services; using DevExpress.AIIntegration.Blazor.Chat.WebView; public partial class Chat : XtraForm { FileStream dataStream; public Chat() { InitializeComponent(); dataStream = File.OpenRead(@"RestaurantMenu.pdf"); /* * In this example, aiChatControl1 was created and configured at design time. */ aiChatControl1.Initialized += AiChatControl1_Initialized; } async void AiChatControl1_Initialized(object sender, AIChatControlInitializedEventArgs e) { await e.SetupAssistantAsync(new OpenAIAssistantOptions("RestaurantMenu.pdf", dataStream, "You are an Analyst Assistant specializing in PDF file analysis. Your role is to assist users by providing accurate answers to their questions about data contained in these files.")); } }
The following screenshot shows the result:
Customize Empty Text
Use the EmptyStateText
property to specify the message displayed when a chat has yet to start:
The following screenshot shows the result: