OpenAI connection for AI AssistView
4 Nov 202524 minutes to read
This section explains about how to connect the AI AssistView with OpenAI.
Creating an application with NuGet reference.
- Create a Wpf desktop app for C# and .NET 6.
- Add reference to Syncfusion.SfChat.Wpf NuGet.
- Import the control namespace
Syncfusion.UI.Xaml.Chatin XAML or C# code. - Initialize the SfAIAssistView control.
- Add reference to Microsoft Semantic NuGet NuGet.
Creating the OpenAI view model class.
To connect with OpenAI, we need the following details.
- OPENAI_KEY: A string variable where we should add our valid OpenAI API key.
- OPENAI_MODEL: A string variable representing the OpenAI language model we want to use.
- API_ENDPOINT: A string variable representing the URL endpoint of the OpenAI API.
public class ViewModel : INotifyPropertyChanged
{
AIAssistChatService service;
private ObservableCollection<object> chats;
public ObservableCollection<object> Chats
{
get
{
return this.chats;
}
set
{
this.chats = value;
RaisePropertyChanged("Messages");
}
}
public DataTemplate AIIcon { get; set; }
private ObservableCollection<string> suggestion;
public void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private Author currentUser;
public Author CurrentUser
{
get
{
return this.currentUser;
}
set
{
this.currentUser = value;
RaisePropertyChanged("CurrentUser");
}
}
private bool showTypingIndicator;
public bool ShowTypingIndicator
{
get
{
return this.showTypingIndicator;
}
set
{
this.showTypingIndicator = value;
RaisePropertyChanged("ShowTypingIndicator");
}
}
public ObservableCollection<string> Suggestion
{
get
{
return this.suggestion;
}
set
{
this.suggestion = value;
RaisePropertyChanged("Suggestion");
}
}
private TypingIndicator typingIndicator;
public TypingIndicator TypingIndicator
{
get
{
return this.typingIndicator;
}
set
{
this.typingIndicator = value;
RaisePropertyChanged("TypingIndicator");
}
}
public ViewModel()
{
this.Chats = new ObservableCollection<object>();
this.Chats.CollectionChanged += Chats_CollectionChanged;
this.CurrentUser = new Author() { Name = "User" };
this.TypingIndicator = new TypingIndicator() { Author = new Author { ContentTemplate = AIIcon } };
service = new AIAssistChatService();
service.Initialize();
}
private async void Chats_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
var item = e.NewItems?[0] as ITextMessage;
if (item != null)
{
if (item.Author.Name == currentUser.Name)
{
ShowTypingIndicator = true;
await service.NonStreamingChat(item.Text);
Chats.Add(new TextMessage
{
Author = new Author { Name = "Bot", ContentTemplate = AIIcon },
DateTime = DateTime.Now,
Text = service.Response
});
ShowTypingIndicator = false;
}
}
}
public class AIAssistChatService
{
IChatCompletionService gpt;
Kernel kernel;
private string OPENAI_KEY = "";// Add a valid OpenAI key here.
private string OPENAI_MODEL = "gpt-4o-mini";
private string API_ENDPOINT = "https://openai.azure.com";
public string Response { get; set; }
public async Task Initialize()
{
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(
OPENAI_MODEL, API_ENDPOINT, OPENAI_KEY);
kernel = builder.Build();
gpt = kernel.GetRequiredService<IChatCompletionService>();
}
public async Task NonStreamingChat(string line)
{
Response = string.Empty;
var response = await gpt.GetChatMessageContentAsync(line);
Response = response.ToString();
}
}
}Bind Messages
Set the ViewModel as the DataContext for the AI AssistView or the parent window. This allows data binding between the UI and the ViewModel properties.
<Page
x:Class="GettingStarted.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:GettingStarted"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:syncfusion="using:Syncfusion.UI.Xaml.Chat"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.DataContext>
<local:ViewModel/>
</Grid.DataContext>
<syncfusion:SfAIAssistView CurrentUser="{Binding CurrentUser}"
Suggestions="{Binding Suggestion}"
ShowTypingIndicator="True"
TypingIndicator="{Binding TypingIndicator}"
Messages="{Binding Chats}"/>
</Grid>
</Page>
Customize AI Response Rendering with ViewTemplateSelector in SfAIAssistView
Use the ViewTemplateSelector property to assign a DataTemplateSelector that controls how messages (including AI responses) are rendered in SfAIAssistView. The selector can return different DataTemplates based on the message type or role (user/assistant/system), enabling rich presentations such as:
- Markdown (via a Markdown viewer like MdXaml)
- FlowDocument-based layouts
- Images and custom visuals
- HTML (via a WebBrowser control or third-party HTML renderer)
This approach lets you tailor the appearance of assistant messages without modifying your data model.
<Page
x:Class="GettingStarted.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:GettingStarted"
xmlns:mdxam="clr-namespace:MdXaml;assembly=MdXaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:syncfusion="using:Syncfusion.UI.Xaml.Chat"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Window.Resources>
<local:ViewTemplateSelector x:Key="viewTS">
<local:ViewTemplateSelector.AITemplate>
<DataTemplate>
<Border Background="Transparent">
<StackPanel>
<Image Height="200" Width="500"
Source="statue-liberty.jpg"
HorizontalAlignment="Left"/>
<mdxam:MarkdownScrollViewer
Markdown="{Binding Text}"
Foreground="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"
VerticalScrollBarVisibility="Auto"
IsHitTestVisible="False"
Padding="8">
<mdxam:MarkdownScrollViewer.MarkdownStyle>
<Style TargetType="FlowDocument" BasedOn="{x:Static mdxam:MarkdownStyle.Standard}">
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Style.Resources>
<Style TargetType="Paragraph" x:Key="H1">
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,0,0,8"/>
</Style>
<Style TargetType="Paragraph" x:Key="H2">
<Setter Property="FontSize" Value="16"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Margin" Value="0,8,0,4"/>
</Style>
<Style TargetType="Image">
<Setter Property="MaxWidth" Value="400"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</Style.Resources>
</Style>
</mdxam:MarkdownScrollViewer.MarkdownStyle>
</mdxam:MarkdownScrollViewer>
</StackPanel>
</Border>
</DataTemplate>
</local:ViewTemplateSelector.AITemplate>
</local:ViewTemplateSelector>
</Window.Resources>
<Grid>
<Grid.DataContext>
<local:ViewModel/>
</Grid.DataContext>
<syncfusion:SfAIAssistView CurrentUser="{Binding CurrentUser}"
Suggestions="{Binding Suggestion}"
ShowTypingIndicator="True"
TypingIndicator="{Binding TypingIndicator}"
Messages="{Binding Chats}"
ViewTemplateSelector="{StaticResource viewTS}"/>
</Grid>
</Page>public class ViewTemplateSelector : DataTemplateSelector
{
public DataTemplate AITemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is AIMessage)
{
return AITemplate;
}
return null;
}
}
public class AIMessage : NotificationObject, ITextMessage
{
private string solution;
/// <summary>
/// Gets or sets the text to be display as the message.
/// </summary>
public string Solution
{
get
{
return this.solution;
}
set
{
this.solution = value;
RaisePropertyChanged(nameof(Solution));
}
}
private Author author;
/// <summary>
/// Gets or sets the author to be display in the message.
/// </summary>
public Author Author
{
get { return author; }
set
{
author = value;
RaisePropertyChanged(nameof(Author));
}
}
private DateTime dateTime;
/// <summary>
/// Gets or sets the date and time details when the message was created.
/// </summary>
public DateTime DateTime
{
get { return dateTime; }
set
{
dateTime = value;
RaisePropertyChanged(nameof(DateTime));
}
}
private string text;
/// <summary>
/// Gets or sets the text to be display as the message.
/// </summary>
public string Text
{
get { return text; }
set { text = value; RaisePropertyChanged(nameof(Text)); }
}
}