Skip to content
Client v5: BLE, BLE Hosting, HTTP, Jobs - Linux, MacOS, & Blazor Support! Full AOT, RX on BLE only & MANY other features! Power up!

ChatView | Getting Started

ChatView is provider-driven. You do two things:

  1. Implement an IChatSessionProvider (your data + real-time layer).
  2. Bind the control’s Provider and SessionId.

That’s the whole integration surface — no Messages collection, no SendCommand, no manual paging.

Add the NuGet package:

Terminal window
dotnet add package Shiny.Maui.Controls

Register in MauiProgram.cs:

builder.UseShinyControls();
// register your provider however you like (singleton/scoped/transient)
builder.Services.AddSingleton<IChatSessionProvider, MyChatSessionProvider>();

Add the XML namespace to your page:

xmlns:shiny="http://shiny.net/maui/controls"

Add the NuGet package:

Terminal window
dotnet add package Shiny.Blazor.Controls

Register your provider and add the using directive:

builder.Services.AddSingleton<IChatSessionProvider, MyChatSessionProvider>();
@using Shiny.Blazor.Controls.Chat
  1. Implement a tiny provider. The provider returns a session-scoped IChatSession handle that owns paging, sending, and the live events. The snippet below is a stub — see The Provider Interface for a complete, runnable in-memory implementation you can copy.

    using Shiny.Maui.Controls.Chat; // Blazor: Shiny.Blazor.Controls.Chat
    public class MyChatSessionProvider : IChatSessionProvider
    {
    readonly Dictionary<string, MyChatSession> sessions = new();
    public Task<IChatSession> CreateSessionAsync(string[] userIds, CancellationToken ct = default)
    {
    var id = Guid.NewGuid().ToString("N");
    var session = new MyChatSession(id, userIds);
    this.sessions[id] = session;
    return Task.FromResult<IChatSession>(session);
    }
    public Task<IChatSession> GetSessionAsync(string sessionId, CancellationToken ct = default)
    {
    if (!this.sessions.TryGetValue(sessionId, out var session))
    throw new ChatSessionException($"Session '{sessionId}' was not found.");
    return Task.FromResult<IChatSession>(session);
    }
    }
  2. Bind Provider + SessionId (MAUI).

    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:shiny="http://shiny.net/maui/controls"
    x:Class="MyApp.ChatPage">
    <shiny:ChatView Provider="{Binding Provider}"
    SessionId="{Binding SessionId}" />
    </ContentPage>
    public partial class ChatViewModel : ObservableObject
    {
    public ChatViewModel(IChatSessionProvider provider)
    {
    this.Provider = provider;
    this.SessionId = "demo";
    }
    public IChatSessionProvider Provider { get; }
    public string SessionId { get; }
    }
  3. Or bind it in Blazor.

    @page "/chat"
    @using Shiny.Blazor.Controls.Chat
    @inject IChatSessionProvider ChatProvider
    <div style="height: 600px;">
    <ChatView Provider="ChatProvider" SessionId="@sessionId" />
    </div>
    @code {
    string sessionId = "demo";
    }

On attach, the control calls GetSessionAsync(SessionId), fetches the newest page via GetMessagesAsync(null, Older, PageSize), subscribes to the session’s events, and renders. On detach it disposes the session.

<shiny:ChatView Provider="{Binding Provider}"
SessionId="{Binding SessionId}"
ChatBackgroundColor="#F0F0F0"
MyBubbleColor="#007AFF"
MyTextColor="White"
OtherBubbleColor="#E5E5EA"
OtherTextColor="Black"
BubbleFontSize="16"
BubbleCornerRadius="12"
PlaceholderText="Ask me anything..."
SendButtonText="Go"
SendButtonBackgroundColor="#34C759"
InputBarBackgroundColor="#FAFAFA"
InputBarBorderColor="#CCCCCC" />
  • The Provider Interface — the full IChatSessionProvider / IChatSession contract and a complete in-memory provider
  • Messages & Paging — the ChatMessage record, cursor paging, and optimistic send
  • Permissions — gate every affordance with ChatSessionPermissions
  • Scenarios — read-only, support, group chat, and FloatingPanel hosting