<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~files/atom-premium.xsl"?>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedpress="https://feed.press/xmlns" xmlns:media="http://search.yahoo.com/mrss/" xmlns:podcast="https://podcastindex.org/namespace/1.0">
  <feedpress:locale>en</feedpress:locale>
  <feedpress:newsletterId>telerik-blogs-mobile</feedpress:newsletterId>
  <link rel="hub" href="https://feedpress.superfeedr.com/"/>
  <logo>https://static.feedpress.com/logo/telerik-blogs--mobile-5ab52ba67db9a.jpg</logo>
  <title type="text">Telerik Blogs | Mobile</title>
  <subtitle type="text">The official blog of Progress Telerik - expert articles and tutorials for developers.</subtitle>
  <id>uuid:c35d869e-6c81-4363-8e06-a9f5732b9144;id=7295</id>
  <updated>2026-05-25T00:09:58Z</updated>
  <link rel="alternate" href="https://www.telerik.com/"/>
  <link rel="self" type="application/atom+xml" href="https://feeds.telerik.com/blogs/mobile"/>
  <entry>
    <id>urn:uuid:b761f26f-90ec-497a-8858-043a53dedcdd</id>
    <title type="text">Installing and Basics of Telerik UI for .NET MAUI AI Coding Assistant</title>
    <summary type="text">Check out the Telerik UI for .NET MAUI AI Coding Assistant, the MCP server native to Telerik controls and MAUI.</summary>
    <published>2026-05-18T14:25:07Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/installing-basics-telerik-ui-net-maui-ai-coding-assistant"/>
    <content type="text"><![CDATA[<p><span class="featured">Check out the Telerik UI for .NET MAUI AI Coding Assistant, the MCP server native to Telerik controls and MAUI.</span></p><p>Code generation using artificial intelligence has improved impressively over the past few months. One of the features that has helped this growth are MCP servers, which allow connecting an AI to information sources quickly. From consulting Microsoft Learn documentation, to those that perform actions on a calendar, to MCP servers for retrieving information from databases, these servers help improve the accuracy of results by obtaining up-to-date and reliable information.</p><p>The team at Progress has released an <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/ai/mcp-server">AI Coding Assistant for .NET MAUI</a>, which helps create and improve graphical interfaces, using the latest features of its UI controls reliably. Let&rsquo;s see it in action.</p><h2 id="what-is-telerik-ui-for-.net-maui-ai-coding-assistant-mcp-server">What Is Telerik UI for .NET MAUI AI Coding Assistant (MCP Server)?</h2><p>Telerik AI Coding Assistant for .NET MAUI is an MCP server that allows retrieving information provided directly by Progress, with the purpose of letting users learn about the use of a specific component or, alternatively, create high-quality graphical interfaces using the latest features and capabilities of the controls in the Telerik suite. Some available features are:</p><ul><li><strong>Prompt handling</strong>: Handles complex prompts</li><li><strong>Client compatibility</strong>: You can use it in different clients, such as VS Code, Cursor, etc.</li><li><strong>Code suggestions</strong>: It can suggest code and perform automatic rebuilds to check for errors</li><li><strong>Response focus</strong>: Focused on code generation</li></ul><p>The above features enable a variety of use cases, including:</p><ul><li><strong>Generation of complex interfaces</strong>: You can rely on the MCP server to generate dashboards, specific pages, etc., requesting the use of specific controls to be used</li><li><strong>Advanced Grid configuration</strong>: Specify which features you need to include in a DataGrid</li><li><strong>Better testing using mock data</strong>: Get a more robust preview by entering test data before connecting to a data source</li><li><strong>Modernization of graphical interfaces</strong>: Refactor your UI, improving it for modern times and better user experiences</li></ul><p>Let&rsquo;s see how to use it.</p><h2 id="installing-telerik-ui-for-.net-maui-ai-coding-assistant-mcp-server">Installing Telerik UI for .NET MAUI AI Coding Assistant (MCP Server)</h2><p>To be able to use Telerik MCP server for .NET MAUI, you must meet some prerequisites:</p><ol><li>A version of .NET equal or greater than 9</li><li>A client compatible with the MCP protocol, such as VS Code, Visual Studio 2026, Cursor, etc.</li><li>A Telerik account</li><li>An active Telerik license (including a trial account)</li><li>A .NET MAUI app that includes the Telerik UI for .NET MAUI controls</li></ol><h2 id="installing-a-license-key">Installing a License Key</h2><p>Before running any command, I recommend that you obtain a <strong>License Key</strong> so your account can be verified and you can use the MCP server. There are several ways to do this. For example, you can go to your <a target="_blank" href="https://www.telerik.com/account">Progress account</a>, where you select the <strong>License Keys</strong> option:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/progress-dashboard-license-keys.png?sfvrsn=bf495214_2" alt="User dashboard showing download area for license keys." /></p><p>On the <strong>License Keys</strong> page, click the <strong>Download License Key</strong> button:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/download-license-key-button.png?sfvrsn=de79abe1_2" alt="Download license key button on settings page" /></p><p>The downloaded file <strong>telerik-license.txt</strong> should be placed in <code>%AppData%\Telerik\telerik-license.txt</code> if you&rsquo;re using Windows, as in my case, or in <code>~/.telerik/telerik-license.txt</code> if you&rsquo;re on Linux. Now, it&rsquo;s time to install the MCP server.</p><h2 id="installing-the-mcp-server">Installing the MCP Server</h2><p>With a License Key on your machine, installing the server is quite simple. In my case I will run the command for <strong>.NET 10</strong>:</p><pre class=" language-text"><code class="prism  language-text">dnx Telerik.MAUI.MCP
</code></pre><p>Once the Telerik MCP for MAUI is installed, the next step is to configure your preferred editor. In the case of VS Code, you should first open the folder containing the .NET MAUI project you&rsquo;ll be working on.</p><p>Then, create a folder at the root named <code>.vscode</code>, inside which you should create a file <code>mcp.json</code>. This file must be replaced or adapted (if you already have previous MCP servers), adding the following entry valid for .NET 10:</p><pre class=" language-json"><code class="prism  language-json"><span class="token punctuation">{</span>
  <span class="token string">"servers"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
    <span class="token string">"telerik-maui-assistant"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
      <span class="token string">"type"</span><span class="token punctuation">:</span> <span class="token string">"stdio"</span><span class="token punctuation">,</span>
      <span class="token string">"command"</span><span class="token punctuation">:</span> <span class="token string">"dnx"</span><span class="token punctuation">,</span>
      <span class="token string">"args"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"Telerik.MAUI.MCP"</span><span class="token punctuation">,</span> <span class="token string">"--yes"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>Alternatively, to use it in Visual Studio, you must create the file <code>.mcp.json</code> at the solution level and add the following content inside:</p><pre class=" language-json"><code class="prism  language-json"><span class="token punctuation">{</span>
  <span class="token string">"servers"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
    <span class="token string">"telerik-maui-assistant"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
      <span class="token string">"type"</span><span class="token punctuation">:</span> <span class="token string">"stdio"</span><span class="token punctuation">,</span>
      <span class="token string">"command"</span><span class="token punctuation">:</span> <span class="token string">"dnx"</span><span class="token punctuation">,</span>
      <span class="token string">"args"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"Telerik.MAUI.MCP"</span><span class="token punctuation">,</span> <span class="token string">"--yes"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>Once done, you will be able to find the new MCP server as part of the tools in both VS Code and Visual Studio 2026:</p><p><strong>VS Code</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/telerik-mcp-server-net-maui-vscode.png?sfvrsn=35a1a02c_2" alt="Telerik MCP server running for .NET MAUI in VS Code" /></p><p><strong>Visual Studio 2026</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/telerik-mcp-setup-maui-vs2026.png?sfvrsn=32760bb7_2" alt="Telerik MCP server setup for .NET MAUI project" /></p><p>With the MCP server configured, we&rsquo;re ready to continue.</p><h2 id="testing-the-telerik-mcp-server-to-create-.net-maui-apps">Testing the Telerik MCP Server to Create .NET MAUI Apps</h2><p>As I mentioned before, the Telerik MCP server can help us perform different tasks.</p><p>For example, suppose you have a page you made using standard .NET MAUI controls, using code similar to the following:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">RowDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Auto,*<span class="token punctuation">"</span></span> <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!-- Header --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
        <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
        <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Product List<span class="token punctuation">"</span></span>
        <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>22<span class="token punctuation">"</span></span>
        <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span>
        <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0,0,0,12<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

    <span class="token comment">&lt;!-- Loading indicator --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ActivityIndicator</span>
        <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
        <span class="token attr-name">IsRunning</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding IsBusy}<span class="token punctuation">"</span></span>
        <span class="token attr-name">IsVisible</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding IsBusy}<span class="token punctuation">"</span></span>
        <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>
        <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

    <span class="token comment">&lt;!-- CollectionView --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>CollectionView</span>
        <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
        <span class="token attr-name">ItemsSource</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Products}<span class="token punctuation">"</span></span>
        <span class="token attr-name">SelectedItem</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SelectedProduct}<span class="token punctuation">"</span></span>
        <span class="token attr-name">SelectionMode</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Single<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>

        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>CollectionView.ItemTemplate</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>DataTemplate</span> <span class="token attr-name"><span class="token namespace">x:</span>DataType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>models:ProductModel<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border</span>
                    <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0,4<span class="token punctuation">"</span></span>
                    <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span>
                    <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{AppThemeBinding Light=White, Dark=#1E1E1E}<span class="token punctuation">"</span></span>
                    <span class="token attr-name">StrokeShape</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RoundRectangle 8<span class="token punctuation">"</span></span>
                    <span class="token attr-name">Stroke</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#E0E0E0<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>

                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>*,Auto<span class="token punctuation">"</span></span> <span class="token attr-name">RowDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Auto,Auto<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>

                        <span class="token comment">&lt;!-- Product name --&gt;</span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                            <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span> <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Name}<span class="token punctuation">"</span></span>
                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16<span class="token punctuation">"</span></span>
                            <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

                        <span class="token comment">&lt;!-- Price --&gt;</span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                            <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span> <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Price, StringFormat=<span class="token punctuation">'</span>${0:F2}<span class="token punctuation">'</span>}<span class="token punctuation">"</span></span>
                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16<span class="token punctuation">"</span></span>
                            <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span>
                            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#512BD4<span class="token punctuation">"</span></span>
                            <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>End<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

                        <span class="token comment">&lt;!-- Category --&gt;</span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                            <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Category}<span class="token punctuation">"</span></span>
                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>13<span class="token punctuation">"</span></span>
                            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Gray<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

                        <span class="token comment">&lt;!-- In Stock badge --&gt;</span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                            <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding InStock, Converter={StaticResource BoolToStockConverter}}<span class="token punctuation">"</span></span>
                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span>
                            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding InStock, Converter={StaticResource BoolToStockColorConverter}}<span class="token punctuation">"</span></span>
                            <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>End<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>DataTemplate</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>CollectionView.ItemTemplate</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>CollectionView</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>In the previous code there isn&rsquo;t much customization, because an unmodified <code>CollectionView</code> is being used:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/dotnet-maui-collectionview-vertical-list.png?sfvrsn=95310cd6_2" alt="Native .NET MAUI CollectionView displaying a vertical list" /></p><p>Although it&rsquo;s true that we could customize it manually through a <code>DataTemplate</code>, most of the time what is required is a quick but robust implementation. Let&rsquo;s use the MCP server to modify the look and feel by giving the following instruction:</p><pre class=" language-text"><code class="prism  language-text">#telerik-maui-assistant  I need you to improve the ProductsPageTelerik page. Replace the CollectionView with a DataGrid. I need the page and its controls to look modern and interactive.
</code></pre><p>When running the instruction and having the Telerik MCP server selected, we will receive a request to run tools, whose information is obtained automatically based on the query made:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/telerik-mcp-maui-permission-prompt.png?sfvrsn=2d8aa7cf_2" alt="Telerik MCP server permission dialog requesting tool execution" /></p><p>With the evolution of AI models, we can achieve that in a single call our instruction is executed, with the GitHub Copilot agent responsible for modifying the code, compiling and testing that everything works correctly. In just a few minutes, the replacement is very precise:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/maui-datagrid-table.png?sfvrsn=ae2254d8_2" alt="Converted DataGrid showing tabular data with columns" /></p><p>Another thing we can do is use the Telerik <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/ai/prompt-library">Prompt Library</a>, which contains a list of prompts for different use cases.</p><p>For example, suppose you&rsquo;d like to add paging to the component. To accomplish this, you can take the prompt <strong>DataGrid with Paging</strong> and adapt it to your use case, as follows:</p><pre class=" language-text"><code class="prism  language-text">#telerik-maui-assistant Modify the DataGrid to include pagination of 20 records per page.
</code></pre><p>Again, after a few calls to the MCP tool, the change is implemented in just a few minutes:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/pagination-added-with-mcp.png?sfvrsn=d786983d_2" alt="Pagination feature added quickly using the MCP server" /></p><p>With the previous exercises, you have been able to verify the power of using the Telerik MCP server for .NET MAUI to create robust graphical interfaces in much less time.</p><h2 id="conclusion">Conclusion</h2><p>In this article you learned about the Telerik UI for .NET MAUI AI Coding Assistant, a powerful MCP server specialized in using Telerik controls to guide you and implement complex graphical interfaces using artificial intelligence.</p><p>Undoubtedly, having this assistant provides a competitive advantage by helping you reduce the time required to create graphical interfaces, while also allowing you to explore design alternatives.</p><hr /><p><strong>Remember:</strong> Telerik UI for .NET MAUI comes with a free 30-day trial. </p><p><a href="https://www.telerik.com/try/ui-for-maui" target="_blank" class="Btn">Try Now</a></p>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:6226fc64-e8ab-4f7f-9a05-3dfe380b4d93</id>
    <title type="text">How to Verify Network Connectivity in .NET MAUI</title>
    <summary type="text">Learn the key steps to checking network connectivity in the various platforms available to your .NET MAUI app.</summary>
    <published>2026-05-11T13:22:15Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/how-to-verify-network-connectivity-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Learn the key steps to checking network connectivity in the various platforms available to your .NET MAUI app.</span></p><p>Identifying the connectivity of the devices running our mobile applications allows us to have much more precise control over the decisions we need to make within the app. From knowing whether the device has internet access, if the connection is limited, and if <strong>connection types such as Bluetooth, WiFi or Ethernet</strong> are active, all this information helps us provide a better user experience.</p><p>For example, we can decide whether to show an empty state when there is no internet connection, prevent certain actions or clearly inform the user about what is happening. This is especially important because, in many cases, the user loses connectivity and assumes the problem is with the application, when in reality it is a network issue.</p><p>Additionally, we can display different scenarios or behaviors depending on the type of connection available, such as when the device only has Bluetooth active or does not have internet access. That&rsquo;s why it&rsquo;s essential to know how to detect these connectivity states. The good news is that in .NET MAUI, we have the ability to do this in a very simple way. Let&rsquo;s take a look! </p><h2 id="first-platform-configuration">First, Platform Configuration</h2><p>Before starting with any implementation, it&rsquo;s important to verify whether you need to apply any platform-specific configuration. Some platforms may require additional setup, while others work out of the box.</p><p>For this, <strong>iOS/Mac Catalyst</strong> and <strong>Windows</strong> require no additional configuration.</p><p>For <strong>Android</strong>, to access connectivity information, you must add the <code>ACCESS_NETWORK_STATE</code> permission. There are three different ways to add this permission on Android:</p><h3 id="android-option-1-add-the-permission-directly-in-the-androidmanifest.xml">Android Option 1: Add the Permission Directly in the AndroidManifest.xml</h3><p>Go to Platforms &rarr; Android, open the AndroidManifest.xml file, and add the following node:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
</code></pre><h3 id="android-option-2-use-the-android-manifest-graphical-editor">Android Option 2: Use the Android Manifest Graphical Editor</h3><p>Go to Platforms &rarr; Android, double-click the AndroidManifest.xml file, and locate the Required permissions section. Find the permission labeled <strong>ACCESS_NETWORK_STATE</strong> and simply check the option, as shown below.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/02_permissions.png?sfvrsn=70ef6bff_2" title="Required permissions" alt="" /></p><h3 id="android-option-3-add-the-assembly-based-permission">Android Option 3: Add the Assembly-based Permission</h3><p>Go to Platforms &rarr; Android &rarr; MainApplication.cs and add the permission as follows:</p><pre class=" language-csharp"><code class="prism  language-csharp">[assembly: UsesPermission(Android.Manifest.Permission.AccessNetworkState)]
</code></pre><h2 id="network-accessibility-in-.net-maui">Network Accessibility in .NET MAUI</h2><p>To inspect the network accessibility on a device, .NET MAUI provides the IConnectivity interface. This is part of the Microsoft.Maui.Networking namespace and is available through the <code>Connectivity.Current</code> property.</p><p>One thing I really like about this API is that it doesn&rsquo;t simply return a boolean value indicating whether there is internet access or not. Instead, it provides much more detailed information, such as the scope of the current network (for example, Internet, ConstrainedInternet and others), as well as details about active connection profiles like Bluetooth, Cellular, WiFi and others. It also exposes an event that allows you to monitor changes in the device&rsquo;s connectivity state in real time.</p><p>Next, we&rsquo;ll take a closer look at each of these values to better understand what they mean and how you can use them in your applications.</p><h2 id="how-to-inspect-the-current-network-scope-">How to Inspect the Current Network Scope? </h2><p>Thanks to the .NET MAUI team, we can determine the scope of the current network in a much more precise way through the <code>NetworkAccess</code> property. This property provides different values that we can evaluate to obtain more detailed information about the device&rsquo;s connectivity state. These values are the following:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/01_internet_connection.png?sfvrsn=f3b0f0be_2" title="Internet connection" alt="" /></p><p>➖ <strong>Internet:</strong> Indicates that the device has access to both the local network and the internet. This is the ideal state for making API calls or performing any action that requires a full internet connection.</p><p>➖ <strong>Local:</strong> The device has access only to the local network.</p><p>➖ <strong>None:</strong> No type of connectivity is available. In this state, it&rsquo;s ideal to inform the user that all or some actions within the app will not work correctly due to the lack of connectivity. This can be done through an empty state, an alert or any other approach that best fits the scenario you&rsquo;re working on.</p><p>➖ <strong>Unknown:</strong> It&rsquo;s not possible to determine the connectivity state. If this happens, while the correct information is being retrieved, it&rsquo;s recommended to inform the user in the same way as in the None state.</p><p>➖ <strong>ConstrainedInternet:</strong> Indicates that the device has limited internet access. This state usually appears when the device is connected to a network with a captive portal, meaning networks that require accepting terms or entering information before granting full internet access. This is common in places like airports, universities or hotels.</p><p>Thanks to all these states, as developers we can be much more specific in how we communicate connectivity issues to our users and better adapt the behavior of our applications.</p><p>For the code implementation, you can do something like what I show below:</p><pre class=" language-csharp"><code class="prism  language-csharp">NetworkAccess accessType = Connectivity.Current.NetworkAccess; 

if (accessType == NetworkAccess.Internet) 
{ 
    // Add the code that you need here 
}
</code></pre><h2 id="checking-active-connection-profiles">Checking Active Connection Profiles</h2><p>While NetworkAccess tells us how accessible the network is (internet, local, none, etc.), ConnectionProfiles allows us to know which type of connection the device is actively using at a given moment.</p><p>The types of connections we can detect are the following:</p><ul><li><strong>WiFi</strong></li><li><strong>Cellular</strong> (mobile data)</li><li><strong>Bluetooth</strong></li><li><strong>Ethernet</strong></li></ul><p>This information is extremely useful for making decisions within your application. For example:</p><ul><li>You can limit your app to download files <strong>only when the device is connected to a WiFi network</strong>.</li><li>Enable local features <strong>when only a Bluetooth connection is available</strong>.</li></ul><p>It&rsquo;s important to keep in mind that <strong>Connectivity.Current.ConnectionProfiles</strong> returns a collection (<code>IEnumerable&lt;ConnectionProfile&gt;</code>), because a device can have multiple connection types active at the same time. For instance, the device may be connected to WiFi while Bluetooth is enabled simultaneously.</p><p>In code, the implementation would look like the following:</p><pre class=" language-csharp"><code class="prism  language-csharp">IEnumerable&lt;ConnectionProfile&gt; profiles = Connectivity.Current.ConnectionProfiles;

if (profiles.Contains(ConnectionProfile.WiFi)) 
{ 
    // Add the code that you need here. 
}
</code></pre><h2 id="reacting-to-connectivity-changes">Reacting to Connectivity Changes</h2><p>We know that network conditions can change at any moment. For this reason, .NET MAUI provides the <code>ConnectivityChanged</code> event, which allows us to detect when network access or active connection profiles change. This makes it possible for our applications to react immediately to these changes, without breaking the app experience.</p><p>Let&rsquo;s take a look at an example based on the official documentation:</p><pre class=" language-csharp"><code class="prism  language-csharp">public class ConnectivityListener 
{ 
    public ConnectivityListener() 
    { 
    Connectivity.ConnectivityChanged += OnConnectivityChanged; 
    }
     
    void OnConnectivityChanged(object sender, ConnectivityChangedEventArgs e) 
    { 
    if (e.NetworkAccess != NetworkAccess.Internet) 
    { 
    Console.WriteLine("No internet connection available."); 
    return; 
    }
     
    if (e.ConnectionProfiles.Contains(ConnectionProfile.WiFi)) 
    { 
    Console.WriteLine("Connected via Wi-Fi."); 
    } 
    else if (e.ConnectionProfiles.Contains(ConnectionProfile.Cellular)) 
    { 
    Console.WriteLine("Using mobile data."); 
    } 
    } 
}
</code></pre><h2 id="⚠️-important-considerations">⚠️ Important Considerations</h2><p><strong>NetworkAccess.Internet:</strong> Due to how connectivity detection works on each platform, .NET MAUI can only detect that a network connection is available. It does not guarantee that the connection has real internet access. For example, a device may be connected to a WiFi network, but the router itself may not have an internet connection.</p><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, you explored how to work with network connectivity in .NET MAUI using Connectivity. You learned how to determine the scope of the current network, detect active connection profiles such as WiFi, Cellular, Bluetooth and Ethernet, and react to connectivity changes in real time using the <code>ConnectivityChanged</code> event.</p><p>With this knowledge, you can now make better decisions in your apps, provide clearer feedback to users and build more resilient experiences that adapt to changing network conditions.</p><p>See you in the next article! &zwj;♀️✨</p><h3 id="references">References</h3><p>Code samples and explanations were based on the official documentation:</p><ul><li><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/communication/networking?view=net-maui-10.0&amp;tabs=android">https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/communication/networking?view=net-maui-10.0&amp;tabs=android</a></li></ul><aside><hr data-sf-ec-immutable="" /><div class="row"><div class="col-4 u-normal-full u-small-mb0"><h4 class="u-fs20 u-fw5 u-lh125 u-mb0">Get Your .NET MAUI App Up More Quickly</h4></div><div class="col-8"><p class="u-fs16 u-mb0">Deliver native apps for every platform in half the time with 70+ customizable UI components, an AI Coding Assistant and unmatched productivity tools. <a href="https://www.telerik.com/maui-ui" target="_blank">Check out Progress Telerik UI for .NET MAUI</a>.</p></div></div></aside>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:3ff0a7d1-e5ec-4f1e-8409-1e23c12969cd</id>
    <title type="text">Integrating Haptic Feedback in .NET MAUI</title>
    <summary type="text">Learn how to give your users interactive feedback with long or short haptic vibration in your .NET MAUI application.</summary>
    <published>2026-05-04T17:04:07Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/integrating-haptic-feedback-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Learn how to give your users interactive feedback with long or short haptic vibration in your .NET MAUI application.</span></p><p>From my experience, keeping users continuously informed about in-app activity is one of the most important retention strategies.</p><p>This feedback can take different forms. For example:</p><ul><li>A message indicating that a record could not be created because the email format isn&rsquo;t valid</li><li>An empty state that informs the user that the app is not working due to a loss of internet connection</li><li>Sound feedback that confirms an action such as a successful transaction</li></ul><p>However, there is another type of feedback that goes beyond visuals or sound: <strong>feedback that can be felt.</strong> This is where haptic feedback comes into play. This type of feedback is usually expressed through a device vibration to notify the user that an action has occurred.</p><p>Common examples include banking applications that vibrate when a transaction is completed successfully, or gaming apps that use vibrations to indicate a collision or an important in-game event. This type of interaction can help create a closer and more natural communication between the user and the application.</p><p>The good news is that today you will learn how to integrate <strong>haptic feedback</strong> into your .NET MAUI applications in a simple and very fast way! </p><h2 id="what-exactly-is-ihapticfeedback-">What Exactly Is IHapticFeedback? </h2><p>IHapticFeedback is an interface in the Microsoft.Maui.Devices namespace that allows you to trigger device vibrations and can be accessed through the HapticFeedback.Default property.</p><p>Haptic feedback provides two different sensation modes that we can trigger in our application:</p><h3 id="click">Click</h3><p>This refers to a short and subtle vibration. It&rsquo;s a great option when we want to provide feedback for simple interactions, such as tapping a button, selecting an item from a list or performing quick actions.</p><h3 id="longpress">LongPress</h3><p>This produces a longer vibration compared to Click. It&rsquo;s mainly used for actions that require more attention or have greater importance, such as confirming a transaction or notifying the user about a relevant event.</p><p>Through HapticFeedback, we can specify which type of sensation we want to trigger. Let&rsquo;s see how to get it implemented.</p><h2 id="initial-setup">Initial Setup</h2><p>For <strong>Android</strong>, we need authorization in our application in order to vibrate the device. This permission can be added in three different ways, which we&rsquo;ll look at below.</p><p>For <strong>iOS / Mac Catalyst</strong> and <strong>Windows</strong>, no initial setup is required.</p><h3 id="android-option-1-add-it-directly-to-the-android-manifest">Android Option 1: Add It Directly to the Android Manifest</h3><p>You can find this file at Platforms ➖ Android ➖ AndroidManifest.xml. Open it and add the following line:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;uses-permission android:name="android.permission.VIBRATE" /&gt;
</code></pre><h3 id="android-option-2-using-the-android-manifest-editor">Android Option 2: Using the Android Manifest Editor</h3><p>Go to <strong>Platforms ➖ Android</strong>, double-click the <strong>AndroidManifest.xml</strong> file and locate the <strong>Required permissions</strong> section. Find the permission labeled <strong>VIBRATE</strong> and simply check the option, as shown below.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/01_permissions.png?sfvrsn=1942c2a0_2" title="Required permissions" alt="" /></p><p>This automatically adds the same line we saw in the first option, but through a graphical interface.</p><h3 id="android-option-3-adding-the-assembly-based-permission">Android Option 3: Adding the Assembly-based Permission</h3><p>Go to the file Platforms ➖Android ➖ MainApplication.cs and add the permission as follows:</p><pre class=" language-csharp"><code class="prism  language-csharp">[assembly: UsesPermission(Android.Manifest.Permission.Vibrate)]
</code></pre><h2 id="how-to-implement-haptic-feedback">How to Implement Haptic Feedback?</h2><p>Once we understand what haptic feedback is and have the correct platform configuration in place, adding it to our project is very easy.</p><h3 id="click-short-haptic">Click (Short Haptic)</h3><pre class=" language-csharp"><code class="prism  language-csharp">private void HapticShortButton_Clicked(object sender, EventArgs e) =&gt;

HapticFeedback.Default.Perform(HapticFeedbackType.Click);
</code></pre><p>Taking a closer look, this code represents an event handler that contains the following:</p><ul><li><p><strong>HapticFeedback.Default:</strong> retrieves the default system implementation for the current device.</p></li><li><p><strong>.Perform(HapticFeedbackType.Click):</strong> tells the system to execute a Click haptic feedback immediately.</p></li></ul><h3 id="longpress-longer-haptic">LongPress (Longer Haptic)</h3><pre class=" language-csharp"><code class="prism  language-csharp">private void HapticLongButton_Clicked(object sender, EventArgs e) =&gt;

HapticFeedback.Default.Perform(HapticFeedbackType.LongPress);
</code></pre><p>This works exactly the same way as the previous example, but changes the feedback type to <strong>LongPress</strong>, resulting in a stronger and longer tactile response.</p><h3 id="connecting-haptic-feedback-to-a-button">Connecting Haptic Feedback to a Button</h3><p>Let&rsquo;s look at a simple example using buttons in XAML:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button Text="Short Haptic" Clicked="HapticShortButton_Clicked"/&gt;

&lt;Button Text="Long Haptic" Clicked="HapticLongButton_Clicked"/&gt;
</code></pre><p>With this setup, each button triggers a different type of haptic feedback when clicked, allowing the user to feel the interaction directly through the device.</p><h3 id="-platform-considerations"> Platform Considerations</h3><ul><li>On Apple, haptic feedback must be triggered from the UI thread.</li></ul><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, you learned what <strong>haptic feedback</strong> is and how it can significantly improve user experience by providing tactile confirmation for user interactions in your .NET MAUI applications.</p><p>You also explored the different types of haptic feedback available&mdash;<strong>Click</strong> and <strong>LongPress</strong>&mdash;and when to use each one, as well as the platform-specific setup required, especially on Android, to enable the feature to work correctly across devices.</p><p>With these concepts in mind, you now have a clear understanding of how to integrate haptic feedback in a simple and effective way, enhancing interaction, usability, and overall app retention without adding unnecessary complexity to your code.</p><p>If you have any questions or would like me to cover more .NET MAUI topics, feel free to leave a comment&mdash;I&rsquo;d be happy to help! </p><p>See you in the next article! &zwj;♀️✨</p><h3 id="references">References</h3><p>The explanation was based on the official documentation:</p><ul><li><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/device/haptic-feedback?view=net-maui-10.0&amp;tabs=android">https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/device/haptic-feedback?view=net-maui-10.0&amp;tabs=android</a></li></ul><aside><hr data-sf-ec-immutable="" /><div class="row"><div class="col-4 u-normal-full u-small-mb0"><h4 class="u-fs20 u-fw5 u-lh125 u-mb0">Building Chat Applications with the .NET MAUI Chat (Conversational UI) Control</h4></div><div class="col-8"><p class="u-fs16 u-mb0">The <a target="_blank" href="https://www.telerik.com/blogs/building-chat-applications-net-maui-chat-conversational-ui-control">.NET MAUI Conversational UI (Chat) component allows integrating chat experiences</a> into your mobile and desktop applications. Learn how to work with this chat component, use cases and how to integrate LLM models.</p></div></div></aside>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:3f5e3e2c-0528-4522-a2c8-b3c294e5861d</id>
    <title type="text">Building Chat Applications with the .NET MAUI Chat (Conversational UI) Control</title>
    <summary type="text">The .NET MAUI Conversational UI (Chat) component allows integrating chat experiences into your mobile and desktop applications. Learn how to work with this chat component, use cases and how to integrate LLM models.</summary>
    <published>2026-04-27T19:45:10Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/building-chat-applications-net-maui-chat-conversational-ui-control"/>
    <content type="text"><![CDATA[<p><span class="featured">The .NET MAUI Conversational UI (Chat) component allows integrating chat experiences into your mobile and desktop applications. Learn how to work with this chat component, use cases and how to integrate LLM models.</span></p><p>One of the best ways to connect with a customer is through conversations, whether with a real person or through an AI agent that provides information about the company or solves problems using a knowledge base.</p><p>If you are creating .NET MAUI applications, you should know that in the Progress Telerik suite you can find the <a target="_blank" href="https://www.telerik.com/maui-ui">.NET MAUI Conversational UI (Chat)</a> component, featuring several characteristics that will allow you to create chat-based applications quickly.</p><p>Throughout this post, we will create an app that uses AI models to provide tips on healthy eating. Let&rsquo;s see how to do it!</p><h2 id="understanding-the-radchat-control-from-telerik-for-.net-maui">Understanding the RadChat Control from Telerik for .NET MAUI</h2><p>The <code>RadChat</code> control from Telerik for .NET MAUI is a component that allows users to interact through a conversational interface, production-ready, capable of handling text messages, attachments, voice-to-text integration and full customization so you can adapt it to your own style, among many other features.</p><p>The control is composed of different graphical elements that we can control and modify through code, as shown in the following image:</p><p><img src="https://www.telerik.com/maui-ui/documentation/assets/898f7480b0af1c2627c39907f618d733/chat-visualstructure.png" alt="RadChat Component Visual Structure" /></p><p>Some typical use cases for the control include:</p><ul><li>AI chatbots</li><li>Real-time customer support</li><li>Messaging applications</li><li>Virtual assistants</li><li>Image analysis with vision AI models</li><li>Among many others</li></ul><p>Let&rsquo;s see how to implement the control in a real application.</p><h2 id="setting-up-a-.net-maui-project-to-integrate-chat-conversations">Setting Up a .NET MAUI Project to Integrate Chat Conversations</h2><p>The first and most important thing when using the chat component in our applications is to follow the <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/first-steps-vs">official installation guide</a>, which shows different ways to set up your environment.</p><p>Additionally, if you want to use any AI model, you need to set up the project by installing the corresponding NuGet packages. As a personal preference, I always like to use <code>Microsoft.Extensions.AI</code>, as it greatly simplifies handling requests to both <strong>OpenAI</strong> and <strong>Azure OpenAI</strong>. For this, install the following packages:</p><ul><li><code>Azure.AI.OpenAI</code></li><li><code>Microsoft.Extensions.AI</code></li><li><code>Microsoft.Extensions.AI.OpenAI</code></li></ul><p>Finally, to facilitate handling with the MVVM pattern, I recommend installing the community toolkit through the following package:</p><ul><li><code>CommunityToolkit.Mvvm</code></li></ul><p>With the packages installed, let&rsquo;s implement the control.</p><h2 id="integrating-chat-functionality-into-a-.net-maui-project">Integrating Chat Functionality into a .NET MAUI Project</h2><p>To use the <code>RadChat</code> control in a .NET MAUI application, you need to do this using the <code>RadChat</code> tag as shown in the following example:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ContentPage</span> <span class="token attr-name">...</span>
    <span class="token attr-name"><span class="token namespace">xmlns:</span>telerik</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.telerik.com/2022/xaml/maui<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadChat</span> <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>chat<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ContentPage</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>By including the above code, we will immediately see the chat control in the emulator:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/basic-radchat-interface.png?sfvrsn=e2cb5709_2" alt="Basic RadChat Interface" /></p><h2 id="interacting-with-chat-messages-in-a-.net-maui-app">Interacting with Chat Messages in a .NET MAUI App</h2><p>To work with chat messages, you should know that the class <code>ChatMessage</code> is the basic class for handling messages, which contains the property <code>Author</code>, used to define the information of a participant that will appear in the UI. <code>Author</code> contains data such as <code>Name</code>, <code>Avatar</code> and <code>Data</code>.</p><p>It is possible to extend this class as the control itself does through <code>TextMessage</code>, which inherits from <code>ChatMessage</code> by adding the property <code>Text</code>.</p><p>Knowing this, we will create a list of <code>TextMessage</code> to maintain the conversation history, as well as define the different roles of type <code>Author</code> that will be used in the conversation. For the example, I have created the class <code>ChatViewModel</code>, which looks as follows:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">partial</span> <span class="token keyword">class</span> <span class="token class-name">ChatViewModel</span> <span class="token punctuation">:</span> ObservableObject
<span class="token punctuation">{</span>
    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> ObservableCollection<span class="token operator">&lt;</span>TextMessage<span class="token operator">&gt;</span> items <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> Author Me <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> Author Bot <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token function">ChatViewModel</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        Me <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Author</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"You"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
        Bot <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Author</span> <span class="token punctuation">{</span> Name <span class="token operator">=</span> <span class="token string">"NutriBot"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>

        Items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">TextMessage</span>
        <span class="token punctuation">{</span>
            Author <span class="token operator">=</span> Bot<span class="token punctuation">,</span>
            Text <span class="token operator">=</span> <span class="token string">"Hello!  I'm NutriBot, your AI-powered nutrition assistant.\n\n"</span> <span class="token operator">+</span>
                    <span class="token string">"I can help you with:\n"</span> <span class="token operator">+</span>
                    <span class="token string">"Analyzing how healthy a food is\n"</span> <span class="token operator">+</span>
                    <span class="token string">"Analyzing photos of food or nutrition labels\n"</span> <span class="token operator">+</span>
                    <span class="token string">"Providing recommendations for a healthy diet\n"</span> <span class="token operator">+</span>
                    <span class="token string">"Evaluating recipes\n\n"</span> <span class="token operator">+</span>
                    <span class="token string">"Send me a message or a photo to get started!"</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>On the other hand, the RadChat control has the properties <code>Author</code>, which allows specifying who is interacting, in addition to <code>Items</code>, responsible for managing the message history:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadChat</span>
    <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>chat<span class="token punctuation">"</span></span>
    <span class="token attr-name">Author</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Me}<span class="token punctuation">"</span></span>
    <span class="token attr-name">ItemsSource</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Items}<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
</code></pre><p>For the previous viewmodel to work correctly, remember to configure both the code-behind of your page and the dependency injection as follows:</p><p><strong>MauiProgram.cs</strong></p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">MauiProgram</span>
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> MauiApp <span class="token function">CreateMauiApp</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">var</span> builder <span class="token operator">=</span> MauiApp<span class="token punctuation">.</span><span class="token function">CreateBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
        builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method function">AddTransient<span class="token punctuation">&lt;</span>ChatViewModel<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            
        <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
        <span class="token keyword">return</span> builder<span class="token punctuation">.</span><span class="token function">Build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p><strong>MainPage.xaml.cs</strong></p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token function">MainPage</span><span class="token punctuation">(</span>ChatViewModel viewModel<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token function">InitializeComponent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    BindingContext <span class="token operator">=</span> viewModel<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>Executing the previous code allows you to see the welcome message in the chat history:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/displaying-chat-app-welcome-message.png?sfvrsn=88610ef7_2" alt="Displaying chat app welcome message" /></p><h2 id="receiving-and-returning-chat-messages">Receiving and Returning Chat Messages</h2><p>So far, we have a list of messages in the application; however, there is no real interaction, meaning that messages are not sent or received back. The control has some commands by default that can help us with this task:</p><ul><li><code>SendMessageCommand</code>: executes when a message is sent</li><li><code>PickFileCommand</code>: executes when attempting to attach a file</li><li><code>PickPhotoCommand</code>: executes when wanting to attach a photo</li><li><code>TakePhotoCommand</code>: executes when the camera opens to take a photo</li></ul><p>There are other <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/controls/chat/commands#commands-related-to-attachments">commands for working with attachments</a>, but the main ones are the above.</p><p>Let&rsquo;s implement the functionality to send and receive messages in the viewmodel, creating a property <code>Message</code> that allows binding the user&rsquo;s message, in addition to a method <code>SendMessage</code>, which will be linked to <code>SendMessageCommand</code> as follows:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">partial</span> <span class="token keyword">class</span> <span class="token class-name">ChatViewModel</span> <span class="token punctuation">:</span> ObservableObject
<span class="token punctuation">{</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">string</span> message <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    
    <span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">async</span> Task <span class="token function">SendMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">var</span> messageText <span class="token operator">=</span> Message<span class="token punctuation">;</span>
        Message <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>

        Items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">TextMessage</span> <span class="token punctuation">{</span> Author <span class="token operator">=</span> Me<span class="token punctuation">,</span> Text <span class="token operator">=</span> messageText <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            

        Items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">TextMessage</span> <span class="token punctuation">{</span> Author <span class="token operator">=</span> Bot<span class="token punctuation">,</span> Text <span class="token operator">=</span> <span class="token string">"Message received!"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>In the UI page, you need to bind this pair of elements using <code>Message</code> and <code>SendMessageCommand</code>:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadChat</span> <span class="token attr-name">...</span>
    <span class="token attr-name">Message</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Message}<span class="token punctuation">"</span></span>
    <span class="token attr-name">SendMessageCommand</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SendMessageCommand}<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
</code></pre><p>With these new changes, we can see that there is a response in the chat window after an interaction:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/sending-and-receiving-messages.png?sfvrsn=f503a7ef_2" alt="Sending and receiving messages using predefined commands" /></p><p>Now let&rsquo;s see how to connect an AI model so that we can have more realistic conversations.</p><h2 id="connecting-an-llm-model-to-a-chat-app-in-.net-maui">Connecting an LLM Model to a Chat App in .NET MAUI</h2><p>To use AI in our application, I have created a service-like class that manages the prompt, model information and methods related to obtaining results from the LLM.</p><p>It is worth noting that I have created some variables to store the connection data with the model, solely for demonstration purposes. Ideally, these data should be stored securely on the device, create an external service to handle it, etc.</p><p>The class looks like this:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ChatService</span>
<span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token keyword">string</span> Endpoint <span class="token operator">=</span> <span class="token string">"your-endpoint"</span><span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token keyword">string</span> DeploymentName <span class="token operator">=</span> <span class="token string">"your-deployment-name"</span><span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token keyword">string</span> ApiKey <span class="token operator">=</span> <span class="token string">"your-api-key"</span><span class="token punctuation">;</span>

    <span class="token keyword">private</span> <span class="token keyword">readonly</span> IChatClient _chatClient<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">readonly</span> List<span class="token operator">&lt;</span>ChatMessage<span class="token operator">&gt;</span> _history<span class="token punctuation">;</span>

    <span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token keyword">string</span> SystemPrompt <span class="token operator">=</span> <span class="token string">""</span>"
        You are an expert and friendly nutritionist<span class="token punctuation">.</span> Your role <span class="token keyword">is</span> to<span class="token punctuation">:</span>
        <span class="token operator">-</span> Analyze food photographs and nutrition <span class="token function">labels</span> <span class="token punctuation">(</span>nutrition facts<span class="token punctuation">)</span>
        <span class="token operator">-</span> Evaluate how healthy a food <span class="token keyword">is</span> <span class="token keyword">for</span> a balanced diet
        <span class="token operator">-</span> Provide healthy eating recommendations
        <span class="token operator">-</span> Suggest healthier alternatives when necessary
        <span class="token operator">-</span> Analyze recipes and give your professional opinion
        <span class="token operator">-</span> Answer questions about nutrition<span class="token punctuation">,</span> diets<span class="token punctuation">,</span> and food wellness
        
        When analyzing an image<span class="token punctuation">:</span>
        <span class="token number">1</span><span class="token punctuation">.</span> Identify the food or nutrition label
        <span class="token number">2</span><span class="token punctuation">.</span> Give a rating <span class="token keyword">from</span> <span class="token number">1</span><span class="token operator">-</span><span class="token number">10</span> on how healthy it <span class="token keyword">is</span>
        <span class="token number">3</span><span class="token punctuation">.</span> Explain the nutritional pros and cons
        <span class="token number">4</span><span class="token punctuation">.</span> Suggest improvements or alternatives
        
        Always respond <span class="token keyword">in</span> a concise but informative manner<span class="token punctuation">.</span>
        Don't use emojis<span class="token punctuation">.</span>
        <span class="token string">""</span>"<span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token function">ChatService</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        _chatClient <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AzureOpenAIClient</span><span class="token punctuation">(</span>
                <span class="token keyword">new</span> <span class="token class-name">Uri</span><span class="token punctuation">(</span>Endpoint<span class="token punctuation">)</span><span class="token punctuation">,</span>
                <span class="token keyword">new</span> <span class="token class-name">ApiKeyCredential</span><span class="token punctuation">(</span>ApiKey<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token function">GetChatClient</span><span class="token punctuation">(</span>DeploymentName<span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token function">AsIChatClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        _history <span class="token operator">=</span>
        <span class="token punctuation">[</span>
            <span class="token keyword">new</span><span class="token punctuation">(</span>ChatRole<span class="token punctuation">.</span>System<span class="token punctuation">,</span> SystemPrompt<span class="token punctuation">)</span>
        <span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/// &lt;summary&gt;</span>
    <span class="token comment">/// Sends a text-only message and returns the AI response.</span>
    <span class="token comment">/// &lt;/summary&gt;</span>
    <span class="token keyword">public</span> <span class="token keyword">async</span> Task<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token operator">&gt;</span> <span class="token function">SendMessageAsync</span><span class="token punctuation">(</span><span class="token keyword">string</span> userMessage<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        _history<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">(</span>ChatRole<span class="token punctuation">.</span>User<span class="token punctuation">,</span> userMessage<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">var</span> response <span class="token operator">=</span> <span class="token keyword">await</span> _chatClient<span class="token punctuation">.</span><span class="token function">GetResponseAsync</span><span class="token punctuation">(</span>_history<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">var</span> assistantMessage <span class="token operator">=</span> response<span class="token punctuation">.</span>Text <span class="token operator">?</span><span class="token operator">?</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>

        _history<span class="token punctuation">.</span><span class="token function">AddMessages</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">return</span> assistantMessage<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/// &lt;summary&gt;</span>
    <span class="token comment">/// Sends a message with an image for vision analysis and returns the AI response.</span>
    <span class="token comment">/// &lt;/summary&gt;</span>
    <span class="token keyword">public</span> <span class="token keyword">async</span> Task<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token operator">&gt;</span> <span class="token function">SendMessageWithImageAsync</span><span class="token punctuation">(</span><span class="token keyword">string</span> userMessage<span class="token punctuation">,</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> imageBytes<span class="token punctuation">,</span> <span class="token keyword">string</span> mimeType<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>        
        <span class="token keyword">var</span> contents <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">List</span><span class="token operator">&lt;</span>AIContent<span class="token operator">&gt;</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">new</span> <span class="token class-name">TextContent</span><span class="token punctuation">(</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrWhiteSpace</span><span class="token punctuation">(</span>userMessage<span class="token punctuation">)</span>
                <span class="token operator">?</span> <span class="token string">"Analyze this image from a nutritional perspective. How healthy is it?"</span>
                <span class="token punctuation">:</span> userMessage<span class="token punctuation">)</span><span class="token punctuation">,</span>
            <span class="token keyword">new</span> <span class="token class-name">DataContent</span><span class="token punctuation">(</span>imageBytes<span class="token punctuation">,</span> mimeType<span class="token punctuation">)</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>

        <span class="token keyword">var</span> message <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ChatMessage</span><span class="token punctuation">(</span>ChatRole<span class="token punctuation">.</span>User<span class="token punctuation">,</span> contents<span class="token punctuation">)</span><span class="token punctuation">;</span>
        _history<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">var</span> response <span class="token operator">=</span> <span class="token keyword">await</span> _chatClient<span class="token punctuation">.</span><span class="token function">GetResponseAsync</span><span class="token punctuation">(</span>_history<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">var</span> assistantMessage <span class="token operator">=</span> response<span class="token punctuation">.</span>Text <span class="token operator">?</span><span class="token operator">?</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>

        _history<span class="token punctuation">.</span><span class="token function">AddMessages</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">return</span> assistantMessage<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>In the code above, you can see that the methods <code>SendMessageAsync</code> are defined to send only text messages, and <code>SendMessageWithImageAsync</code> to send text along with images, which prepares us for the following sections.</p><p>To use it, we must update the viewmodel code to receive the instance of the new service:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">partial</span> <span class="token keyword">class</span> <span class="token class-name">ChatViewModel</span> <span class="token punctuation">:</span> ObservableObject
<span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">readonly</span> ChatService _chatService<span class="token punctuation">;</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token keyword">public</span> <span class="token function">ChatViewModel</span><span class="token punctuation">(</span>ChatService chatService<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        _chatService <span class="token operator">=</span> chatService<span class="token punctuation">;</span>
        <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>

    <span class="token keyword">private</span> <span class="token keyword">async</span> Task <span class="token function">SendMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
        <span class="token keyword">try</span>
        <span class="token punctuation">{</span>
            Items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">TextMessage</span> <span class="token punctuation">{</span> Author <span class="token operator">=</span> Me<span class="token punctuation">,</span> Text <span class="token operator">=</span> messageText <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token keyword">var</span> response <span class="token operator">=</span> <span class="token keyword">await</span> _chatService<span class="token punctuation">.</span><span class="token function">SendMessageAsync</span><span class="token punctuation">(</span>messageText<span class="token punctuation">)</span><span class="token punctuation">;</span>

            Items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">TextMessage</span> <span class="token punctuation">{</span> Author <span class="token operator">=</span> Bot<span class="token punctuation">,</span> Text <span class="token operator">=</span> response <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> ex<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            Items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">TextMessage</span>
            <span class="token punctuation">{</span>
                Author <span class="token operator">=</span> Bot<span class="token punctuation">,</span>
                Text <span class="token operator">=</span> $<span class="token string">"⚠️ Error processing your message: {ex.Message}"</span>
            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>In the previous update, you can also see that I have changed the method <code>SendMessage</code>, adding an <code>try-catch</code> for any error that might occur, in addition to using the service to obtain a response from the LLM model. You should also add the new service to the dependency container in <code>MauiProgram.cs</code>:</p><pre class=" language-csharp"><code class="prism  language-csharp">builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method function">AddSingleton<span class="token punctuation">&lt;</span>ChatService<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>With the previous changes, we will see a more realistic response created thanks to an LLM model:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/interacting-with-an-llm-model.png?sfvrsn=83fa7495_2" alt="Interacting with an llm model" /></p><h2 id="attaching-elements-to-the-conversation">Attaching Elements to the Conversation</h2><p>Next, we will see how we can attach images to the conversation, with the purpose of querying the AI model for information about them. The first thing we will do is create a model that represents the attachments:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">partial</span> <span class="token keyword">class</span> <span class="token class-name">AttachedFileData</span> <span class="token punctuation">:</span> ObservableObject
<span class="token punctuation">{</span>
    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">string</span> name <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">long</span> size<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> Func<span class="token operator">&lt;</span>Task<span class="token operator">&lt;</span>Stream<span class="token operator">&gt;</span><span class="token operator">&gt;</span> getStream <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span> Task<span class="token punctuation">.</span><span class="token generic-method function">FromResult<span class="token punctuation">&lt;</span>Stream<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>Stream<span class="token punctuation">.</span>Null<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">?</span> imageBytes<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">string</span><span class="token operator">?</span> mimeType<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>With the class that defines an attachment ready, we can create a list with a generic <code>AttachedFileData</code>, which will allow us to display them in a special section in the chat window.</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">partial</span> <span class="token keyword">class</span> <span class="token class-name">ChatViewModel</span> <span class="token punctuation">:</span> ObservableObject
<span class="token punctuation">{</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> ObservableCollection<span class="token operator">&lt;</span>AttachedFileData<span class="token operator">&gt;</span> attachedFiles <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">async</span> Task <span class="token function">AttachFile</span><span class="token punctuation">(</span>IList<span class="token operator">&lt;</span>AttachedFileData<span class="token operator">&gt;</span><span class="token operator">?</span> filesToAttach<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>filesToAttach <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span>
        
        <span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token keyword">var</span> file <span class="token keyword">in</span> filesToAttach<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            AttachedFiles<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>file<span class="token punctuation">)</span><span class="token punctuation">;</span>                
        <span class="token punctuation">}</span>
        
        filesToAttach<span class="token punctuation">.</span><span class="token function">Clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre><p>In the code above, we have also defined a method called <code>AttachFile</code>, which will allow us to attach the attachments to the list. In the graphic control, we need to perform two operations.</p><ol><li>Activate the button to attach files via <code>IsMoreButtonVisible</code></li><li>Bind <code>AttachFilesCommand</code> to the viewmodel method</li><li>Bind <code>AttachedFilesSource</code> to <code>AttachedFiles</code></li></ol><p>We can see this below:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadChat</span> <span class="token attr-name">...</span>
    <span class="token attr-name">AttachFilesCommand</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding AttachFilesCommand}<span class="token punctuation">"</span></span>
    <span class="token attr-name">AttachedFilesSource</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding AttachedFiles}<span class="token punctuation">"</span></span>
    <span class="token attr-name">IsMoreButtonVisible</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>True<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
</code></pre><p>With the previous modifications, we will see a new button to attach attachments. Although we might think that the above is enough for the LLM to respond correctly to messages with images, if we try to query something with an attached image, we will get a response regarding the LLM model&rsquo;s unawareness of the attached file:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/attaching-files-without-favorable-llm-responses.png?sfvrsn=cabb71e0_2" alt="Attaching files without successful llm response" /></p><p>This happens because we have not added the attached file to the message list. To achieve this, several steps need to be followed:</p><ol><li>Detect when the collection of files changes:</li></ol><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token function">ChatViewModel</span><span class="token punctuation">(</span>ChatService chatService<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
   <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>    
    AttachedFiles<span class="token punctuation">.</span>CollectionChanged <span class="token operator">+</span><span class="token operator">=</span> OnAttachedFilesChanged<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><ol start="2"><li>Create the event handler for when the collection changes. This will allow adding the corresponding information according to the type of file:</li></ol><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">private</span> <span class="token keyword">async</span> <span class="token keyword">void</span> <span class="token function">OnAttachedFilesChanged</span><span class="token punctuation">(</span><span class="token keyword">object</span><span class="token operator">?</span> sender<span class="token punctuation">,</span> NotifyCollectionChangedEventArgs e<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>Action <span class="token operator">==</span> NotifyCollectionChangedAction<span class="token punctuation">.</span>Add <span class="token operator">&amp;&amp;</span> e<span class="token punctuation">.</span>NewItems <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">foreach</span> <span class="token punctuation">(</span>AttachedFileData file <span class="token keyword">in</span> e<span class="token punctuation">.</span>NewItems<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">await</span> <span class="token function">LoadFileData</span><span class="token punctuation">(</span>file<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">private</span> <span class="token keyword">async</span> Task <span class="token function">LoadFileData</span><span class="token punctuation">(</span>AttachedFileData file<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">try</span>
    <span class="token punctuation">{</span>
        <span class="token comment">// Load the image bytes from the stream</span>
        <span class="token keyword">using</span> <span class="token keyword">var</span> stream <span class="token operator">=</span> <span class="token keyword">await</span> file<span class="token punctuation">.</span><span class="token function">GetStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">using</span> <span class="token keyword">var</span> ms <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MemoryStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">await</span> stream<span class="token punctuation">.</span><span class="token function">CopyToAsync</span><span class="token punctuation">(</span>ms<span class="token punctuation">)</span><span class="token punctuation">;</span>
        file<span class="token punctuation">.</span>ImageBytes <span class="token operator">=</span> ms<span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// Try to determine MIME type from file extension</span>
        <span class="token keyword">var</span> extension <span class="token operator">=</span> Path<span class="token punctuation">.</span><span class="token function">GetExtension</span><span class="token punctuation">(</span>file<span class="token punctuation">.</span>Name<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ToLowerInvariant</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        file<span class="token punctuation">.</span>MimeType <span class="token operator">=</span> extension <span class="token keyword">switch</span>
        <span class="token punctuation">{</span>
            <span class="token string">".jpg"</span> or <span class="token string">".jpeg"</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token string">"image/jpeg"</span><span class="token punctuation">,</span>
            <span class="token string">".png"</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token string">"image/png"</span><span class="token punctuation">,</span>
            <span class="token string">".gif"</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token string">"image/gif"</span><span class="token punctuation">,</span>
            <span class="token string">".webp"</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token string">"image/webp"</span><span class="token punctuation">,</span>
            _ <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token string">"image/jpeg"</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>
                        
    <span class="token punctuation">}</span>
    <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> ex<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        Items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">TextMessage</span>
        <span class="token punctuation">{</span>
            Author <span class="token operator">=</span> Bot<span class="token punctuation">,</span>
            Text <span class="token operator">=</span> $<span class="token string">"⚠️ Error loading file {file.Name}: {ex.Message}"</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><ol start="3"><li>In addition to the above, we need to modify the method for sending messages. Before doing that, to display the new messages in the history, we need to create a new class to handle the image information. In our case, it is as follows:</li></ol><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">partial</span> <span class="token keyword">class</span> <span class="token class-name">ChatMessageItem</span> <span class="token punctuation">:</span> ObservableObject
<span class="token punctuation">{</span>
    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">object</span><span class="token operator">?</span> author<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">string</span> text <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">?</span> imageData<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">string</span><span class="token operator">?</span> imageMimeType<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">string</span><span class="token operator">?</span> imageFileName<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>With this change, we can now update the method that sends the messages, adding the necessary code for a message to contain information about the image. Make sure to change all references from <code>TextMessage</code> to <code>ChatMessageItem</code>:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>
<span class="token keyword">private</span> <span class="token keyword">async</span> Task <span class="token function">SendMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">var</span> messageText <span class="token operator">=</span> Message<span class="token punctuation">;</span>
    <span class="token keyword">var</span> filesToSend <span class="token operator">=</span> AttachedFiles<span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Message <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>

    <span class="token keyword">try</span>
    <span class="token punctuation">{</span>        
        <span class="token keyword">if</span> <span class="token punctuation">(</span>filesToSend<span class="token punctuation">.</span>Count <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">var</span> file <span class="token operator">=</span> filesToSend<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
            
            Items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ChatMessageItem</span>
            <span class="token punctuation">{</span>
                Author <span class="token operator">=</span> Me<span class="token punctuation">,</span>
                Text <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrWhiteSpace</span><span class="token punctuation">(</span>messageText<span class="token punctuation">)</span>
                    <span class="token operator">?</span> <span class="token string">" Analyzing this image..."</span>
                    <span class="token punctuation">:</span> messageText<span class="token punctuation">,</span>
                ImageData <span class="token operator">=</span> file<span class="token punctuation">.</span>ImageBytes<span class="token punctuation">,</span>
                ImageMimeType <span class="token operator">=</span> file<span class="token punctuation">.</span>MimeType<span class="token punctuation">,</span>
                ImageFileName <span class="token operator">=</span> file<span class="token punctuation">.</span>Name
            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            
            <span class="token keyword">var</span> response <span class="token operator">=</span> <span class="token keyword">await</span> _chatService<span class="token punctuation">.</span><span class="token function">SendMessageWithImageAsync</span><span class="token punctuation">(</span>
                <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrWhiteSpace</span><span class="token punctuation">(</span>messageText<span class="token punctuation">)</span>
                    <span class="token operator">?</span> <span class="token string">"Analyze this image from a nutritional perspective."</span>
                    <span class="token punctuation">:</span> messageText<span class="token punctuation">,</span>
                file<span class="token punctuation">.</span>ImageBytes<span class="token operator">!</span><span class="token punctuation">,</span>
                file<span class="token punctuation">.</span>MimeType <span class="token operator">?</span><span class="token operator">?</span> <span class="token string">"image/jpeg"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            Items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ChatMessageItem</span> <span class="token punctuation">{</span> Author <span class="token operator">=</span> Bot<span class="token punctuation">,</span> Text <span class="token operator">=</span> response <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">else</span>
        <span class="token punctuation">{</span>
           <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><p>If you try to run the application at this moment, you will encounter an exception like the following:</p><pre class=" language-text"><code class="prism  language-text">`Unable to convert item of type MauiRadChatTests.ChatMessageItem to Telerik.Maui.Controls.Chat.ChatItem. You need to set the ItemConverter of the RadChat`.
</code></pre><p>The message is very descriptive about what we need to do: assign a value to <code>ItemConverter</code>. Let&rsquo;s do that next.</p><h2 id="displaying-attachments-in-the-conversation-history">Displaying Attachments in the Conversation History</h2><p>To understand this section, you should know that the control <code>RadChat</code> works internally with its own types, such as <code>ChatItem</code>, <code>ChatAttachedFile</code>, etc. However, in an MVVM architecture, the viewmodel should not know or depend on specific types in the UI. This is why the control mandates the use of some converters to perform a conversion between business objects and graphical control elements.</p><p><code>ItemConverter</code> is a property we need to assign through a class that inherits from <code>IChatItemConverter</code>. Its purpose is to convert a data model <code>ChatMessageItem</code> (or the type you have defined) into a Telerik UI type <code>ChatItem</code>, so that binding to the property <code>ItemsSource</code> can be done correctly.</p><p>The method <code>ConvertToChatItem</code> is used every time <code>RadChat</code> needs to render an element of the collection <code>ItemSource</code>, while <code>ConvertToDataItem</code> is used when RadChat wants to create a new item automatically, such as when the user presses Send. We will use null because we will handle everything from the viewmodel.</p><p>In the following example, you can see how we compare whether it is a text message or an image, and based on that we return either <code>ChatAttachmentsMessage</code> or <code>TextMessage</code>:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ChatItemConverter</span> <span class="token punctuation">:</span> IChatItemConverter
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> ChatItem <span class="token function">ConvertToChatItem</span><span class="token punctuation">(</span><span class="token keyword">object</span> dataItem<span class="token punctuation">,</span> ChatItemConverterContext context<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">var</span> item <span class="token operator">=</span> <span class="token punctuation">(</span>ChatMessageItem<span class="token punctuation">)</span>dataItem<span class="token punctuation">;</span>

        <span class="token keyword">var</span> vm <span class="token operator">=</span> <span class="token punctuation">(</span>ChatViewModel<span class="token punctuation">)</span>context<span class="token punctuation">.</span>Chat<span class="token punctuation">.</span>BindingContext<span class="token punctuation">;</span>
        <span class="token keyword">var</span> author <span class="token operator">=</span> item<span class="token punctuation">.</span>Author <span class="token operator">==</span> vm<span class="token punctuation">.</span>Bot <span class="token operator">?</span> vm<span class="token punctuation">.</span>Bot <span class="token punctuation">:</span> context<span class="token punctuation">.</span>Chat<span class="token punctuation">.</span>Author<span class="token punctuation">;</span>
        
        <span class="token keyword">if</span> <span class="token punctuation">(</span>item<span class="token punctuation">.</span>ImageData <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> item<span class="token punctuation">.</span>ImageData<span class="token punctuation">.</span>Length <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>            
            <span class="token keyword">var</span> imageSource <span class="token operator">=</span> ImageSource<span class="token punctuation">.</span><span class="token function">FromStream</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token keyword">new</span> <span class="token class-name">MemoryStream</span><span class="token punctuation">(</span>item<span class="token punctuation">.</span>ImageData<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            
            <span class="token keyword">var</span> attachment <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ChatAttachment</span>
            <span class="token punctuation">{</span>
                FileName <span class="token operator">=</span> item<span class="token punctuation">.</span>ImageFileName <span class="token operator">?</span><span class="token operator">?</span> <span class="token string">"image.jpg"</span><span class="token punctuation">,</span>
                FileSize <span class="token operator">=</span> item<span class="token punctuation">.</span>ImageData<span class="token punctuation">.</span>Length<span class="token punctuation">,</span>
                Data <span class="token operator">=</span> imageSource<span class="token punctuation">,</span>
                GetFileStream <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span> Task<span class="token punctuation">.</span><span class="token generic-method function">FromResult<span class="token punctuation">&lt;</span>Stream<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">MemoryStream</span><span class="token punctuation">(</span>item<span class="token punctuation">.</span>ImageData<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token punctuation">}</span><span class="token punctuation">;</span>

            <span class="token keyword">var</span> attachmentMessage <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ChatAttachmentsMessage</span>
            <span class="token punctuation">{</span>
                Data <span class="token operator">=</span> dataItem<span class="token punctuation">,</span>
                Author <span class="token operator">=</span> author<span class="token punctuation">,</span>
                Text <span class="token operator">=</span> item<span class="token punctuation">.</span>Text<span class="token punctuation">,</span>
                Attachments <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">List</span><span class="token operator">&lt;</span>ChatAttachment<span class="token operator">&gt;</span> <span class="token punctuation">{</span> attachment <span class="token punctuation">}</span>
            <span class="token punctuation">}</span><span class="token punctuation">;</span>

            <span class="token keyword">return</span> attachmentMessage<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        
        <span class="token keyword">var</span> textMessage <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TextMessage</span>
        <span class="token punctuation">{</span>
            Data <span class="token operator">=</span> dataItem<span class="token punctuation">,</span>
            Author <span class="token operator">=</span> author<span class="token punctuation">,</span>
            Text <span class="token operator">=</span> item<span class="token punctuation">.</span>Text
        <span class="token punctuation">}</span><span class="token punctuation">;</span>

        <span class="token keyword">return</span> textMessage<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">object</span><span class="token operator">?</span> <span class="token function">ConvertToDataItem</span><span class="token punctuation">(</span><span class="token keyword">object</span> message<span class="token punctuation">,</span> ChatItemConverterContext context<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>        
        <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>In the above code, you can see that we are very specific in loading the image through the use of <code>ImageSource.FromStream</code>, necessary to bind a <code>Image</code> control to an image. This converter needs to be bound to the property <code>ItemConverter</code> as we saw in the exception description:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ContentPage</span>
    <span class="token attr-name">...</span>
    <span class="token attr-name"><span class="token namespace">xmlns:</span>converters</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>clr-namespace:MauiRadChatTests<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>


    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ContentPage.Resources</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">converters:</span>ChatItemConverter</span> <span class="token attr-name"><span class="token namespace">x:</span>Key</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>ChatItemConverter<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ContentPage.Resources</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadChat</span> <span class="token attr-name">...</span>       
        <span class="token attr-name">ItemConverter</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{StaticResource ChatItemConverter}<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ContentPage</span><span class="token punctuation">&gt;</span></span>

</code></pre><p>Now, if we tried to run the application again, we would receive the following error:</p><pre class=" language-text"><code class="prism  language-text">The AttachedFileConverter is null. This converter must be set, so that the RadChat can automatically convert IFileInfo instances to a business object that represents an attached file, and add them to the AttachedFilesSource collection. Alternatively, you can add attachments objects in your view model via the AttachFilesCommand or AttachFiles event.
</code></pre><p>The previous error tells us that we need to implement a second converter, necessary to convert a business object and add it to the collection of attachments. This means we need to implement a class that implements the <code>IChatAttachedFileConverter</code> interface, which will be responsible for translating our file model <code>AttachedFileData</code> to a <code>ChatAttachedFile</code> from Telerik.</p><p>In our case, the converter looks like this:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AttachedFileConverter</span> <span class="token punctuation">:</span> IChatAttachedFileConverter
<span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> AttachedFileConverter<span class="token operator">?</span> _instance<span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> AttachedFileConverter Instance <span class="token operator">=</span><span class="token operator">&gt;</span> _instance <span class="token operator">?</span><span class="token operator">?</span><span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AttachedFileConverter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> ChatAttachedFile <span class="token function">ConvertToChatAttachedFile</span><span class="token punctuation">(</span><span class="token keyword">object</span> dataItem<span class="token punctuation">,</span> ChatAttachedFileConverterContext context<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">var</span> data <span class="token operator">=</span> <span class="token punctuation">(</span>AttachedFileData<span class="token punctuation">)</span>dataItem<span class="token punctuation">;</span>
        <span class="token keyword">var</span> chatAttachedFile <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ChatAttachedFile</span>
        <span class="token punctuation">{</span>
            Data <span class="token operator">=</span> data<span class="token punctuation">,</span>
            FileName <span class="token operator">=</span> data<span class="token punctuation">.</span>Name<span class="token punctuation">,</span>
            FileSize <span class="token operator">=</span> data<span class="token punctuation">.</span>Size
        <span class="token punctuation">}</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> chatAttachedFile<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">object</span> <span class="token function">ConvertToDataItem</span><span class="token punctuation">(</span>Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Controls<span class="token punctuation">.</span>IFileInfo fileToAttach<span class="token punctuation">,</span> ChatAttachedFileConverterContext context<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token function">CreateAttachedFileData</span><span class="token punctuation">(</span>fileToAttach<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">internal</span> <span class="token keyword">static</span> AttachedFileData <span class="token function">CreateAttachedFileData</span><span class="token punctuation">(</span>Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Controls<span class="token punctuation">.</span>IFileInfo file<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">AttachedFileData</span>
        <span class="token punctuation">{</span>
            Name <span class="token operator">=</span> file<span class="token punctuation">.</span>FileName<span class="token punctuation">,</span>
            Size <span class="token operator">=</span> file<span class="token punctuation">.</span>FileSize<span class="token punctuation">,</span>
            GetStream <span class="token operator">=</span> file<span class="token punctuation">.</span>OpenReadAsync<span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>In the control, we must assign the instance of the class to <code>AttachedFileConverter</code>, preferably allowing a single instance through the use of <code>x:Static</code>:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadChat</span> <span class="token attr-name">...</span>
    <span class="token attr-name">AttachedFileConverter</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{x:Static converters:AttachedFileConverter.Instance}<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
</code></pre><p>With the implementation of the previous changes, it is now possible to run the application, which returns information on a query of type image + text:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/radchat-control-in-action-receiving-text-and-images.gif?sfvrsn=7c266654_2" alt="RadChat control in action receiving text and images" /></p><p>With this, we have created a useful and real application based on a chat component, which we developed quickly and easily thanks to the controls from the Telerik suite for .NET MAUI.</p><h2 id="conclusion">Conclusion</h2><p>Throughout this post, we have explored the .NET MAUI Conversational UI (Chat) component, which allows integrating chat experiences into your applications. We have seen how to configure it, the parts that make it up, use cases, how to integrate LLM models for its usage, among other topics.</p><p>This is just the beginning, as in the official documentation you can find other relevant topics about customizing the control. See you in the next post.</p><h3 id="want-to-try-it-yourself">Want to Try It Yourself?</h3><p>The Telerik UI for .NET MAUI component library comes with a free 30-day trial. So go ahead!</p><p><a target="_blank" href="https://www.telerik.com/try/ui-for-maui" class="Btn">Try Now</a></p>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:89e0e3fc-f615-4718-b937-f4de1ceba07a</id>
    <title type="text">Introducing the Progress Agentic RAG .NET SDK</title>
    <summary type="text">The .NET SDK for Progress Agentic RAG provides Retrieval-Augmented Generation (RAG) capabilities to .NET development with knowledge base management, AI-powered search and resource operations.</summary>
    <published>2026-04-23T15:33:21Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Ed Charbeneau </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/introducing-progress-agentic-rag-net-sdk"/>
    <content type="text"><![CDATA[<p><span class="featured">The .NET SDK for Progress Agentic RAG provides Retrieval-Augmented Generation (RAG) capabilities to .NET development with knowledge base management, AI-powered search and resource operations.</span></p><h2>What Is Progress Agentic RAG?</h2><p>Progress Agentic RAG is a RAG-as-a-Service that makes it dramatically easier to build AI systems grounded in real, trusted content. Rather than wiring together vector databases, embedding pipelines and retrieval logic yourself, Progress Agentic RAG provides an end-to-end platform for indexing, understanding and retrieving multimodal data.</p><p>It enables intelligent, agent-driven workflows that combine structured knowledge, contextual search and LLM orchestration into a unified experience.</p><p>With the introduction of the .NET SDK for Progress Agentic RAG, .NET developers can integrate this capability directly into their applications with just a few lines of code, leveraging modern .NET architecture patterns such as dependency injection, async workflows and strongly typed APIs.</p><h3>From Retrieval to Agentic Intelligence</h3><p>Progress Agentic RAG offers a fully capable AI Search Dashboard solution that allows you to get started in a matter of minutes. Simply connect or upload your data to a Knowledge Box, wait for NucliaDB&rsquo;s blazing-fast indexing engine to process it, and you&rsquo;re ready to explore grounded, contextual AI responses.</p><p>That immediate productivity is powerful. But modern enterprise development requires more than a dashboard.</p><p>Enterprise environments demand typed APIs, strong tooling and predictable behavior. Many RAG solutions are Python-first, leaving .NET teams stitching together REST calls manually and building custom abstractions just to regain the ergonomics they expect from their platform.</p><p>The new .NET SDK changes that.</p><p>It provides:</p><ul style="margin-top:0in;" type="disc"><li>Strongly typed APIs</li><li>Async-first patterns</li><li>Native .NET integration</li><li>Simplified knowledge base interaction</li></ul><p>With these capabilities, you can move beyond simple retrieval and begin composing intelligent, agent-driven experiences directly inside your application architecture. As powerful as it is convenient, the .NET SDK makes a great choice for new AI-enabled .NET applications.</p><h2>Getting Started</h2><p>Once a Knowledge Box has been established, you can begin interacting with Progress Agentic RAG through the .NET SDK.</p><p>The SDK is distributed as a <a target="_blank" href="https://www.nuget.org/packages/Progress.Nuclia">NuGet package</a> and covers the complete NucliaDB REST API. That includes strongly typed models, structured output helpers, dependency injection extensions and more than 200 APIs that expose the full surface area of the platform. See the <a target="_blank" href="https://docs.rag.progress.cloud/docs/develop/dotnet-sdk/">SDK documentation page </a>for a comprehensive list of service providers available.</p><h3>Install the NuGet Package</h3><pre><code class="language-csharp">dotnet add package Progress.Nuclia</code></pre><p>With the package installed, you can register the INucliaDb interface using modern dependency injection patterns. The SDK supports everything from basic configuration to advanced multi-tenant scenarios using keyed services.</p><h3>Register the Client</h3><pre><code class="language-csharp">using Progress.Nuclia.Extensions;

// Create configuration
var config = new NucliaDbConfig(
    ZoneId: "aws-us-east-2-1",
    KnowledgeBoxId: "your-knowledge-box-id",
    ApiKey: "your-api-key"
);

// Register with logging
builder.Services.AddNucliaDb(config).UseLogging();</code></pre><p>This approach aligns naturally with ASP.NET Core&rsquo;s architecture. You configure once, inject where needed, and keep your AI integration cleanly separated from business logic.</p><h2>Ask Questions with Agentic RAG</h2><p>With configuration complete, you can begin querying your Knowledge Box using AskAsync or AskStreamingAsync.</p><pre><code class="language-csharp">// Make request
AskRequest askRequest = new("What issues are driving the most customer escalations this quarter?");
var response = await client.Search.AskAsync(askRequest);

// Display answer
Console.WriteLine(response.Data.Answer);</code></pre><p>In just a few lines of code, you&rsquo;re executing a grounded, agent-driven query against indexed enterprise data.</p><p>The Ask functionality is only the beginning. With more than 200 APIs available in the SDK, you can ingest and manage resources, create conversational interactions and perform search, all using strongly typed, async-first C# patterns.</p><p>With structured configuration and native .NET integration in place, you can move from experimentation to production-ready AI systems with confidence.</p><h2>Explore the Examples: Blazor and .NET MAUI</h2><p>The fastest way to understand what Progress Agentic RAG can do in a real application is to see it running inside the frameworks you already use.</p><p>We&rsquo;ve published hands-on examples built with:</p><ul style="margin-top:0in;" type="disc"><li><a target="_blank" href="https://github.com/telerik/telerik-blazor-progress-rag-demo">Blazor &mdash; showcasing grounded AI experiences in modern web applications</a></li><li><a target="_blank" href="https://github.com/telerik/telerik-maui-progress-rag-demo">NET MAUI &mdash; demonstrating cross-platform, AI-powered mobile and desktop apps</a></li></ul><p>These samples go beyond simple API calls. They show how to:</p><ul style="margin-top:0in;" type="disc"><li>Register the SDK using dependency injection</li><li>Execute agentic queries with structured output</li><li>Stream responses into interactive UI components</li><li>Keep AI concerns cleanly separated from presentation logic</li></ul><p>If you&rsquo;re building internal tools, customer-facing dashboards or cross-platform AI assistants, these examples provide a production-oriented starting point.</p><p>Clone the samples, wire up your Knowledge Box and see how quickly you can integrate grounded, agent-driven intelligence into your existing .NET architecture.</p><h2>Additional Media</h2><p>Learn more about Progress Agentic RAG and the .NET SDK from video tutorials and podcasts:</p><ul><li>The Progress Agentic RAG .NET SDK was featured on episode 1997 of .NET Rocks:&nbsp;<a target="_blank" href="https://www.dotnetrocks.com/details/1997">.NET Rocks! Agentic RAG with Ed Charbeneau</a></li><li>Getting started videos by Jeff (Csharp) Fritz</li></ul><div sf-youtube-url="https://youtu.be/ilJpB9Y7waA?si=nIm6nTg2HLc0Bvkf"><iframe frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" title="Build Your First AI Search in .NET with Progress Agentic RAG" width="640" height="360" src="https://www.youtube.com/embed/ilJpB9Y7waA?si=nIm6nTg2HLc0Bvkf&amp;enablejsapi=1&amp;origin=https%3A%2F%2Fwww.telerik.com&amp;widgetid=3&amp;forigin=https%3A%2F%2Fwww.telerik.com%2FSitefinity%2Fadminapp%2Fcontent%2Fblogs%2Fc2c9ae54-03a9-4243-86cc-9c50fcc0a754%2Fblogposts%2F89e0e3fc-f615-4718-b937-f4de1ceba07a%2Fedit%3Fsf_provider%3DOpenAccessDataProvider%26sf_culture%3Den&amp;aoriginsup=1&amp;vf=1"></iframe></div><div sf-youtube-url="https://youtu.be/qE6zy75btLo?si=ZferEV00m-sRamDA"><iframe frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" title="Build Your First AI Search in .NET with Progress Agentic RAG Part 2" width="640" height="360" src="https://www.youtube.com/embed/qE6zy75btLo?si=ZferEV00m-sRamDA&amp;enablejsapi=1&amp;origin=https%3A%2F%2Fwww.telerik.com&amp;widgetid=2&amp;forigin=https%3A%2F%2Fwww.telerik.com%2FSitefinity%2Fadminapp%2Fcontent%2Fblogs%2Fc2c9ae54-03a9-4243-86cc-9c50fcc0a754%2Fblogposts%2F89e0e3fc-f615-4718-b937-f4de1ceba07a%2Fedit%3Fsf_provider%3DOpenAccessDataProvider%26sf_culture%3Den&amp;aoriginsup=1&amp;vf=1"></iframe></div>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:e7198ac4-e43c-42a1-8e88-88cfb9d9655c</id>
    <title type="text">Building an Instagram-Style Like Animation in .NET MAUI</title>
    <summary type="text">Learn how to make your .NET MAUI app a little more engaging with interactive animations. We’ll see how to animate a heart for a like action.</summary>
    <published>2026-04-13T15:56:16Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/building-instagram-style-like-animation-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Learn how to make your .NET MAUI app a little more engaging with interactive animations. We&rsquo;ll see how to animate a heart for a like action.</span></p><p>One of the most rewarding aspects of software development is being able to replicate interfaces and behaviors from applications we use every day. Seeing a familiar interaction come to life in our own product&mdash;while respecting its essence and behavior&mdash;is undoubtedly very satisfying.</p><p>In this article, we&rsquo;ll explore some of the basic animations available in .NET MAUI and how we can combine them to recreate one of Instagram&rsquo;s most recognizable interactions: the like animation when tapping the heart. Through a practical example, we&rsquo;ll see how to implement this behavior in a clear and straightforward way.</p><p>The goal is to help you lose the fear of working with animations in .NET MAUI. Sometimes we assume animation is too complicated or that it&rsquo;s better not to attempt it at all. But the reality is that when used correctly and combined thoughtfully, even the most basic animations can produce great results. And the best part: with just a few lines of code, you can achieve this Instagram-like effect.</p><p>For better guidance, we&rsquo;ll divide this article into the following phases:</p><ul><li>We&rsquo;ll build a simple interface that represents the base structure of an Instagram post.</li><li>We&rsquo;ll start working with animations, walking through each step with its corresponding code example.</li><li>Finally, we will see a result of the explained code.</li></ul><h2 id="demo-of-the-goal-before-we-start-">Demo of the Goal Before We Start </h2><p>Before jumping into the implementation, here&rsquo;s a quick demo of how the Instagram-like animation we&rsquo;re building will look.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/01_instagram_post_structure.png?sfvrsn=4ec560ef_2" title="Instagram post structure" alt="Photo of two girls giving peace signs. Below are icons for likes, comments, reposts, shares" /></p><h2 id="building-the-structure-of-an-instagram-post-in-xaml">Building the Structure of an Instagram Post in XAML</h2><p>To better understand the animation, we&rsquo;ll first recreate a simplified Instagram post UI in XAML. This structure will serve as the foundation for our animation and should look like the example shown below.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/02_instagram_demo_animation.gif?sfvrsn=e763eb5f_2" title="Instagram like animation Demo" alt="When user clicks the heart, it pops up in a fun animation" /></p><p>To replicate the basic structure of an Instagram post, we&rsquo;ll start by adding a VerticalStackLayout. This layout will contain the user image, followed by a Grid that will be responsible for organizing the action icons: like, comment, repost and send.</p><p>Although, for now, we&rsquo;ll only animate the heart icon, including the remaining actions helps make the example feel more realistic and closer to a real Instagram post design. </p><p>Let&rsquo;s begin by creating the <strong>VerticalStackLayout</strong> and adding the <strong>Image</strong>.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;VerticalStackLayout&gt;
    &lt;Image Source="models.png" 
       Aspect="AspectFill" 
       HeightRequest="350" /&gt; 
    &lt;!-- Add all the remaining code here -- &gt;
&lt;/VerticalStackLayout&gt;
</code></pre><p>Okay, now let&rsquo;s open a <strong>Grid</strong>. Initially, we&rsquo;ll add all the elements that are not related to the like interaction, so that later we can focus exclusively on the XAML for the &ldquo;likes.&rdquo;</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid ColumnDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto"
    Padding="20,10" 
    ColumnSpacing="10"&gt;
    
    &lt;!-- Add likes implementation in the space --&gt; 
    &lt;Label Grid.Column="1" Text="5" /&gt;
    
    &lt;!-- Comments --&gt; 
    &lt;Image Grid.Column="2" Source="comment" WidthRequest="15" HeightRequest="15" /&gt; 
    &lt;Label Grid.Column="3" Text="23" /&gt;
    
    &lt;!-- Repost --&gt; 
    &lt;Image Grid.Column="4" Source="repost" WidthRequest="15" HeightRequest="15" /&gt; 
    &lt;Label Grid.Column="5" Text="1" /&gt;
    
    &lt;!-- Send --&gt; 
    &lt;Image Grid.Column="6" Source="send" WidthRequest="15" HeightRequest="15" /&gt; 
    &lt;Label Grid.Column="7" Text="2" /&gt; 
&lt;/Grid&gt;
</code></pre><h2 id="adding-likes-in-the-xaml">Adding Likes in the XAML</h2><p>Although there are different ways to implement this behavior&mdash;such as leveraging VisualState&mdash;for this example, we&rsquo;ll keep the approach intentionally simple. The goal is to take a closer look at how components like Grid and GestureRecognizers behave and how we can take advantage of them to build animations in a clear and controlled way.</p><p>We&rsquo;ll need three images to achieve the animation:</p><ul><li><strong>Outline image:</strong> When the post has not been liked yet, this is a heart with a transparent background and black outline.</li><li><strong>Filled image:</strong> When the post is liked, this is a solid heart (no outline) and it will remain hidden until the &ldquo;liked&rdquo; state needs to be displayed.</li><li><strong>Animated overlay :</strong> The image that will be used exclusively to display the animation.</li></ul><p>In XAML, this translates to the following. In the code example above, locate the line that says <code>&lt;!-- Add likes implementation in the space --&gt;</code> and replace it with the following code:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid Grid.Column="0" 
WidthRequest="15" 
HeightRequest="15"&gt;

&lt;Image x:Name="HeartIcon" 
    Source="heartoutline" 
    WidthRequest="15" 
    HeightRequest="15"&gt;

&lt;Image.GestureRecognizers&gt; 
    &lt;TapGestureRecognizer Tapped="OnHeartTapped" /&gt;
&lt;/Image.GestureRecognizers&gt; 
&lt;/Image&gt;

&lt;Image x:Name="HeartFilled"
    Source="heartfilledred" 
    WidthRequest="15" 
    HeightRequest="15" 
    Opacity="0" 
    InputTransparent="True" /&gt;

&lt;Image x:Name="HeartBurst" 
    Source="heartfilledred" 
    WidthRequest="15" 
    HeightRequest="15" 
    Opacity="0" 
    Scale="1" 
    TranslationY="0" 
    InputTransparent="True" /&gt; 
&lt;/Grid&gt;
</code></pre><p>✍️ We added a <strong>GestureRecognizer</strong> to the heart in its initial state. This allows us to detect the tap gesture and trigger the animation accordingly.</p><blockquote><p>If you&rsquo;d like to learn more about <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/gestures/tap?view=net-maui-10.0">GestureRecognizers</a>, I recommend you check out this MS Learn article.</p></blockquote><h2 id="bringing-the-like-interaction-to-life-">Bringing the Like Interaction to Life </h2><p>In the previous XAML, we added an image with the name <code>HeartIcon</code> and associated it with an event called <code>OnHeartTapped</code>. The next step is to give that event a body and define what should happen when the user taps the heart.</p><p>The first thing we need is a variable that represents the current like state:</p><pre class=" language-csharp"><code class="prism  language-csharp">bool _isLiked;
</code></pre><p>Then, let&rsquo;s implement the <code>OnHeartTapped</code> event:</p><pre class=" language-csharp"><code class="prism  language-csharp">void OnHeartTapped(object sender, EventArgs e) 
{ 
    if (_isLiked) 
    { 
    SetLiked(false); 
    return; 
    }

    _ = PlayLikeAnimationAsync(); 
}
</code></pre><h3 id="what-happens-in-this-event">What Happens in This Event?</h3><ul><li>Every time the heart is tapped, we first check whether it is already marked as liked.<br />If it is, that means the user wants to remove the like. So we set it to false using <code>SetLiked(false)</code>.</li><li>If the post is not liked, it means we need to trigger the heart animation. We do that by calling <code>PlayLikeAnimationAsync()</code>.</li></ul><p>⚠️ <code>PlayLikeAnimationAsync</code> has not been created yet; we will add it and give it a body in the next steps.</p><p>Now that we know when the animation should be triggered, the next step is to create the <code>PlayLikeAnimationAsync</code> method to life. But before implementing it, let&rsquo;s do a brief overview of the animations we will be using:</p><ul><li><p><strong>FadeTo:</strong> allows us to progressively change the opacity of a visual element. It receives values between <strong>0</strong> and <strong>1.</strong></p><p> In our case, we use it to show or hide the heart while the like animation is happening.</p></li><li><p><strong>TranslateTo:</strong> this animation is responsible for moving the element along the <strong>X</strong> axis (horizontal movement) and the <strong>Y</strong> axis (vertical movement).</p><p> In our animation, we use it to simulate the heart jumping upward and then returning to its initial position.</p></li></ul><p>To be able to run these animations simultaneously, we will use <code>Task.WhenAll</code>.</p><p>There are also two additional methods, <code>SetLiked()</code> and <code>ResetWithEmptyHeart()</code>, which we will cover and explain in the next steps.</p><p>Now, let&rsquo;s see how all of this translates into code below.</p><pre class=" language-csharp"><code class="prism  language-csharp">async Task PlayLikeAnimationAsync() 
{ 
    if (_isLiked) return;
    
    await Task.WhenAll( 
    HeartBurst.FadeTo(1, 80, Easing.CubicOut), 
    HeartBurst.TranslateTo(0, -35, 160, Easing.CubicOut)
    );
    
    await Task.WhenAll( 
    HeartBurst.TranslateTo(0, 0, 120, Easing.CubicInOut)
    );
    
    SetLiked(true); 
    ResetWithEmptyHeart();
}
</code></pre><p>To close the animation flow, we rely on two methods that serve very specific purposes: <code>SetLiked</code> and <code>ResetWithEmptyHeart</code>.</p><h3 id="setliked">SetLiked</h3><p>This method is responsible for updating the visual state of the heart. Basically, if the like is true, we hide the <code>HeartIcon</code> (outline) and show the <code>HeartFilled</code>. If the like is false, we do the opposite: we show the outline icon and hide the filled icon.</p><p>In code, it looks like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">void SetLiked(bool liked) 
{ 
    _isLiked = liked; 
    HeartIcon.Opacity = liked ? 0 : 1; 
    HeartFilled.Opacity = liked ? 1 : 0; 
}
</code></pre><h3 id="resetwithemptyheart">ResetWithEmptyHeart</h3><p>Finally, we have the <code>ResetWithEmptyHeart()</code> method. This one is responsible for cleaning up and resetting the animated image (<code>HeartBurst</code>) once the animation has finished, so that it always starts from a clean state the next time it runs.</p><p>In code, it would look like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">void ResetWithEmptyHeart()    
 {
    HeartBurst.Opacity = 0; 
    HeartBurst.TranslationY = 0;
}
</code></pre><p>Here we reset:</p><ul><li>The opacity, so the animated heart is no longer visible.</li><li>And the vertical position, bringing the heart back to its starting point.</li></ul><p>And with this implementation, the animation is now complete.  It should behave as follows:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/03_instagram_like_animation.gif?sfvrsn=749c2f0c_2" title="Instagram like animations" alt="Heart like and unlike behaviors" /></p><aside><hr /><div class="row"><div class="col-4 u-normal-full u-small-mb0"><h4 class="u-fs20 u-fw5 u-lh125 u-mb0">Want to learn more about animations in .NET MAUI? </h4></div><div class="col-8"><p class="u-fs16 u-mb0">I recommend reading the official documentation article on
                <a href="https://learn.microsoft.com/en-us/dotnet/maui/user-interface/animation/basic?view=net-maui-10.0" target="_blank">basic animations in .NET MAUI</a>.
 </p></div></div><hr class="u-mb3" /></aside><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In a super simple way, we were able to replicate the Instagram like animation in .NET MAUI. We built it step by step so you could clearly understand how it works and, in the same way, apply this implementation to your everyday needs as a .NET MAUI developer.</p><p>If you have any questions or would like me to dive deeper into specific topics, feel free to leave a comment&mdash;I&rsquo;ll be happy to help! </p><p>See you in the next article! &zwj;♀️</p>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:6480f9af-1aef-43f5-959f-cab45ab104fc</id>
    <title type="text">Getting Started with the .NET MAUI Speech-to-Text Button Control</title>
    <summary type="text">Add speech-to-text options to your note-taking, chat, meeting or many other types of apps, so your users can skip manual typing in your .NET MAUI app.</summary>
    <published>2026-04-02T19:58:04Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/getting-started-net-maui-speech-to-text-button-control"/>
    <content type="text"><![CDATA[<p><span class="featured">Add speech-to-text options to your note-taking, chat, meeting or many other types of apps, so your users can skip manual typing in your .NET MAUI app.</span></p><p>For several years, a common problem for mobile device users has been typing text quickly. Although innovative features such as swipe typing and word autocompletion have been implemented, undoubtedly one of the most comfortable methods remains voice dictation.</p><p>In .NET MAUI, you can take advantage of the Progress Telerik UI for <a target="_blank" href="https://www.telerik.com/maui-ui/speech-to-text-button">.NET MAUI SpeechToTextButton</a> control, which allows converting speech to text. Let&rsquo;s see how to use it in your own .NET MAUI apps!</p><h2 id="getting-to-know-the-telerik-speechtotextbutton-control-for-.net-maui">Getting to Know the Telerik SpeechToTextButton Control for .NET MAUI</h2><p>The SpeechToTextButton control uses platform-specific voice recognition services to perform speech-to-text conversion, including <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/controls/speechtotextbutton/winui-support">WinUI</a>. The structure of the control is simple, and it is based on a button composed of a <strong>SpeechToTextButton Content</strong> and a <strong>SpeechToTextButton</strong>, which you can see in the following image:</p><p><img src="https://www.telerik.com/maui-ui/documentation/assets/e12eb57a64e50c12e588881ba7414605/speechtotextbutton-visual-structure.png" alt="Diagram showing the structure of Telerik’s SpeechToTextButton control for .NET MAUI" /></p><p>Some possible use cases for the control are:</p><ul><li>Voice note-taking</li><li>Chat applications</li><li>Voice search</li><li>Command control via voice</li><li>Meeting transcription</li><li>Among many others</li></ul><p>In reality, the range of use cases is quite large. Now let&rsquo;s analyze the control in more depth.</p><h2 id="creating-a-practical-case">Creating a Practical Case</h2><p>Let&rsquo;s start by creating a demo application, which will help us see the different features of the speech-to-text control. The idea of the application is to be a personal note-taking app that allows actions like editing text, saving notes and sharing them.</p><p>For this example, we&rsquo;ll use the <strong>CommunityToolkit.Mvvm</strong> package, which allows for rapid creation of view models. Below, I show you the initial code for the application in case you want to replicate it, which is as follows:</p><p><strong>TextEditorPage.xaml</strong>:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span>
    <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>20<span class="token punctuation">"</span></span>
    <span class="token attr-name">RowDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Auto, Auto, *, Auto<span class="token punctuation">"</span></span>
    <span class="token attr-name">RowSpacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!--  Header Section  --&gt;</span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
        <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span>
        <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>28<span class="token punctuation">"</span></span>
        <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Fast Note<span class="token punctuation">"</span></span>
        <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#1A1A2E<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

    <span class="token comment">&lt;!--  Status Bar  --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border</span>
        <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
        <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16,12<span class="token punctuation">"</span></span>
        <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#F3F4F6<span class="token punctuation">"</span></span>
        <span class="token attr-name">StrokeShape</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RoundRectangle 12<span class="token punctuation">"</span></span>
        <span class="token attr-name">StrokeThickness</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Auto, *, Auto<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span>
                <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span>
                <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding CharacterCount}<span class="token punctuation">"</span></span>
                <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#9CA3AF<span class="token punctuation">"</span></span>
                <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!--  Main Editor Area  --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border</span>
        <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span>
        <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
        <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#FFFFFF<span class="token punctuation">"</span></span>
        <span class="token attr-name">Stroke</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#E5E7EB<span class="token punctuation">"</span></span>
        <span class="token attr-name">StrokeShape</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RoundRectangle 16<span class="token punctuation">"</span></span>
        <span class="token attr-name">StrokeThickness</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">RowDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>*, Auto<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Editor</span>
                <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>MainEditor<span class="token punctuation">"</span></span>
                <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16<span class="token punctuation">"</span></span>
                <span class="token attr-name">AutoSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>TextChanges<span class="token punctuation">"</span></span>
                <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Transparent<span class="token punctuation">"</span></span>
                <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16<span class="token punctuation">"</span></span>
                <span class="token attr-name">Placeholder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Start typing or use voice input...<span class="token punctuation">"</span></span>
                <span class="token attr-name">PlaceholderColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#9CA3AF<span class="token punctuation">"</span></span>
                <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding EditorText, Mode=TwoWay}<span class="token punctuation">"</span></span>
                <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#1F2937<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

            <span class="token comment">&lt;!--  Editor Toolbar  --&gt;</span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border</span>
                <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12,0<span class="token punctuation">"</span></span>
                <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#F9FAFB<span class="token punctuation">"</span></span>
                <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>56<span class="token punctuation">"</span></span>
                <span class="token attr-name">StrokeThickness</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>*, Auto, Auto<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                    <span class="token comment">&lt;!--  Word Count  --&gt;</span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>VerticalStackLayout</span> <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span>
                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding WordCount}<span class="token punctuation">"</span></span>
                            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#6B7280<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>VerticalStackLayout</span><span class="token punctuation">&gt;</span></span>

                    <span class="token comment">&lt;!--  Clear Button  --&gt;</span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Button</span>
                        <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12,8<span class="token punctuation">"</span></span>
                        <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Transparent<span class="token punctuation">"</span></span>
                        <span class="token attr-name">BorderWidth</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Command</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding ClearTextCommand}<span class="token punctuation">"</span></span>
                        <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>14<span class="token punctuation">"</span></span>
                        <span class="token attr-name">IsEnabled</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding HasText}<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Clear<span class="token punctuation">"</span></span>
                        <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#EF4444<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

                    <span class="token comment">&lt;!--  Copy Button  --&gt;</span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Button</span>
                        <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12,8<span class="token punctuation">"</span></span>
                        <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Transparent<span class="token punctuation">"</span></span>
                        <span class="token attr-name">BorderWidth</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Command</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding CopyTextCommand}<span class="token punctuation">"</span></span>
                        <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>14<span class="token punctuation">"</span></span>
                        <span class="token attr-name">IsEnabled</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding HasText}<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Copy<span class="token punctuation">"</span></span>
                        <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#3B82F6<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!--  Quick Actions  --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span>
        <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>3<span class="token punctuation">"</span></span>
        <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>*, *, *<span class="token punctuation">"</span></span>
        <span class="token attr-name">ColumnSpacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Button</span>
            <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#E5E7EB<span class="token punctuation">"</span></span>
            <span class="token attr-name">BorderWidth</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
            <span class="token attr-name">Command</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding NewDocumentCommand}<span class="token punctuation">"</span></span>
            <span class="token attr-name">CornerRadius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span>
            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>14<span class="token punctuation">"</span></span>
            <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>44<span class="token punctuation">"</span></span>
            <span class="token attr-name">IsEnabled</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding HasText}<span class="token punctuation">"</span></span>
            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>New<span class="token punctuation">"</span></span>
            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#374151<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Button</span>
            <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
            <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#10B981<span class="token punctuation">"</span></span>
            <span class="token attr-name">BorderWidth</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
            <span class="token attr-name">Command</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SaveTextCommand}<span class="token punctuation">"</span></span>
            <span class="token attr-name">CornerRadius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span>
            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>14<span class="token punctuation">"</span></span>
            <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>44<span class="token punctuation">"</span></span>
            <span class="token attr-name">IsEnabled</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding HasText}<span class="token punctuation">"</span></span>
            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Save<span class="token punctuation">"</span></span>
            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#FFFFFF<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Button</span>
            <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span>
            <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#8B5CF6<span class="token punctuation">"</span></span>
            <span class="token attr-name">BorderWidth</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
            <span class="token attr-name">Command</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding ShareTextCommand}<span class="token punctuation">"</span></span>
            <span class="token attr-name">CornerRadius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span>
            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>14<span class="token punctuation">"</span></span>
            <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>44<span class="token punctuation">"</span></span>
            <span class="token attr-name">IsEnabled</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding HasText}<span class="token punctuation">"</span></span>
            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Share<span class="token punctuation">"</span></span>
            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#FFFFFF<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
</code></pre><p><strong>TextEditorPage.xaml.cs</strong>:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">partial</span> <span class="token keyword">class</span> <span class="token class-name">TextEditorPage</span> <span class="token punctuation">:</span> ContentPage
<span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">readonly</span> TextEditorViewModel _viewModel<span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token function">TextEditorPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token function">InitializeComponent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        _viewModel <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TextEditorViewModel</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        BindingContext <span class="token operator">=</span> _viewModel<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p><strong>TextEditorViewModel.cs</strong>:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">partial</span> <span class="token keyword">class</span> <span class="token class-name">TextEditorViewModel</span> <span class="token punctuation">:</span> ObservableObject
<span class="token punctuation">{</span>
    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token punctuation">[</span><span class="token function">NotifyPropertyChangedFor</span><span class="token punctuation">(</span><span class="token function">nameof</span><span class="token punctuation">(</span>CharacterCount<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
    <span class="token punctuation">[</span><span class="token function">NotifyPropertyChangedFor</span><span class="token punctuation">(</span><span class="token function">nameof</span><span class="token punctuation">(</span>WordCount<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
    <span class="token punctuation">[</span><span class="token function">NotifyPropertyChangedFor</span><span class="token punctuation">(</span><span class="token function">nameof</span><span class="token punctuation">(</span>HasText<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">string</span> _editorText <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">string</span> _statusText <span class="token operator">=</span> <span class="token string">"Ready"</span><span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> Color _statusColor <span class="token operator">=</span> Colors<span class="token punctuation">.</span>Gray<span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">string</span> CharacterCount <span class="token operator">=</span><span class="token operator">&gt;</span> $<span class="token string">"{EditorText?.Length ?? 0} characters"</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">string</span> WordCount
    <span class="token punctuation">{</span>
        <span class="token keyword">get</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">int</span> words <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrWhiteSpace</span><span class="token punctuation">(</span>EditorText<span class="token punctuation">)</span>
                <span class="token operator">?</span> <span class="token number">0</span>
                <span class="token punctuation">:</span> EditorText<span class="token punctuation">.</span><span class="token function">Split</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">' '</span><span class="token punctuation">,</span> <span class="token string">'\n'</span><span class="token punctuation">,</span> <span class="token string">'\r'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> StringSplitOptions<span class="token punctuation">.</span>RemoveEmptyEntries<span class="token punctuation">)</span><span class="token punctuation">.</span>Length<span class="token punctuation">;</span>
            <span class="token keyword">return</span> $<span class="token string">"{words} words"</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">bool</span> HasText <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token operator">!</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>EditorText<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token preprocessor property">#<span class="token directive keyword">region</span> Commands</span>

    <span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">ClearText</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        EditorText <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>
        <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Text cleared"</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">async</span> Task <span class="token function">CopyTextAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>HasText<span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span>

        <span class="token keyword">await</span> Clipboard<span class="token punctuation">.</span>Default<span class="token punctuation">.</span><span class="token function">SetTextAsync</span><span class="token punctuation">(</span>EditorText<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Copied to clipboard"</span><span class="token punctuation">,</span> <span class="token string">"#10B981"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">await</span> Task<span class="token punctuation">.</span><span class="token function">Delay</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Ready"</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">async</span> Task <span class="token function">NewDocumentAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>HasText<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>Application<span class="token punctuation">.</span>Current<span class="token operator">?</span><span class="token punctuation">.</span>Windows<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">.</span>Page <span class="token keyword">is</span> Page page<span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">bool</span> confirm <span class="token operator">=</span> <span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">DisplayAlertAsync</span><span class="token punctuation">(</span><span class="token string">"New Document"</span><span class="token punctuation">,</span>
                    <span class="token string">"Do you want to create a new document? Current text will be lost."</span><span class="token punctuation">,</span>
                    <span class="token string">"Yes"</span><span class="token punctuation">,</span> <span class="token string">"No"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

                <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>confirm<span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>

        EditorText <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>
        <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"New document created"</span><span class="token punctuation">,</span> <span class="token string">"#10B981"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">async</span> Task <span class="token function">SaveTextAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">var</span> page <span class="token operator">=</span> Application<span class="token punctuation">.</span>Current<span class="token operator">?</span><span class="token punctuation">.</span>Windows<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">.</span>Page<span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>page <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>HasText<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">DisplayAlertAsync</span><span class="token punctuation">(</span><span class="token string">"Save"</span><span class="token punctuation">,</span> <span class="token string">"There is no text to save."</span><span class="token punctuation">,</span> <span class="token string">"OK"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">try</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">string</span> fileName <span class="token operator">=</span> $<span class="token string">"VoiceNote_{DateTime.Now:yyyyMMdd_HHmmss}.txt"</span><span class="token punctuation">;</span>
            <span class="token keyword">string</span> filePath <span class="token operator">=</span> Path<span class="token punctuation">.</span><span class="token function">Combine</span><span class="token punctuation">(</span>FileSystem<span class="token punctuation">.</span>AppDataDirectory<span class="token punctuation">,</span> fileName<span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token keyword">await</span> File<span class="token punctuation">.</span><span class="token function">WriteAllTextAsync</span><span class="token punctuation">(</span>filePath<span class="token punctuation">,</span> EditorText<span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Document saved"</span><span class="token punctuation">,</span> <span class="token string">"#10B981"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">DisplayAlertAsync</span><span class="token punctuation">(</span><span class="token string">"Saved"</span><span class="token punctuation">,</span> $<span class="token string">"Document saved as {fileName}"</span><span class="token punctuation">,</span> <span class="token string">"OK"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> ex<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">DisplayAlertAsync</span><span class="token punctuation">(</span><span class="token string">"Error"</span><span class="token punctuation">,</span> $<span class="token string">"Could not save document: {ex.Message}"</span><span class="token punctuation">,</span> <span class="token string">"OK"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>
    <span class="token keyword">private</span> <span class="token keyword">async</span> Task <span class="token function">ShareTextAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>HasText<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>Application<span class="token punctuation">.</span>Current<span class="token operator">?</span><span class="token punctuation">.</span>Windows<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">.</span>Page <span class="token keyword">is</span> Page page<span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">DisplayAlertAsync</span><span class="token punctuation">(</span><span class="token string">"Share"</span><span class="token punctuation">,</span> <span class="token string">"There is no text to share."</span><span class="token punctuation">,</span> <span class="token string">"OK"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">await</span> Share<span class="token punctuation">.</span>Default<span class="token punctuation">.</span><span class="token function">RequestAsync</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ShareTextRequest</span>
        <span class="token punctuation">{</span>
            Text <span class="token operator">=</span> EditorText<span class="token punctuation">,</span>
            Title <span class="token operator">=</span> <span class="token string">"Share Voice Note"</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token preprocessor property">#<span class="token directive keyword">endregion</span></span>

    <span class="token preprocessor property">#<span class="token directive keyword">region</span> Helper Methods</span>

    <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token keyword">string</span> text<span class="token punctuation">,</span> <span class="token keyword">string</span><span class="token operator">?</span> colorHex<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        StatusText <span class="token operator">=</span> text<span class="token punctuation">;</span>
        StatusColor <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>colorHex<span class="token punctuation">)</span> <span class="token operator">?</span> Colors<span class="token punctuation">.</span>Gray <span class="token punctuation">:</span> Color<span class="token punctuation">.</span><span class="token function">FromArgb</span><span class="token punctuation">(</span>colorHex<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">UpdateButtonState</span><span class="token punctuation">(</span>Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>SpeechRecognizer<span class="token punctuation">.</span>SpeechRecognizerState state<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">switch</span> <span class="token punctuation">(</span>state<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">case</span> Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>SpeechRecognizer<span class="token punctuation">.</span>SpeechRecognizerState<span class="token punctuation">.</span>Listening<span class="token punctuation">:</span>
                <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Listening..."</span><span class="token punctuation">,</span> <span class="token string">"#2563EB"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">break</span><span class="token punctuation">;</span>
            <span class="token keyword">case</span> Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>SpeechRecognizer<span class="token punctuation">.</span>SpeechRecognizerState<span class="token punctuation">.</span>Initializing<span class="token punctuation">:</span>
                <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Initializing..."</span><span class="token punctuation">,</span> <span class="token string">"#F59E0B"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">break</span><span class="token punctuation">;</span>
            <span class="token keyword">default</span><span class="token punctuation">:</span>
                <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Ready"</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">break</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token preprocessor property">#<span class="token directive keyword">endregion</span></span>
<span class="token punctuation">}</span>
</code></pre><p>The above code results in the following application when executed:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/showing-a-note-taking-app-interface-being-used-through-a-keyboard.gif?sfvrsn=1143ca0e_2" alt="Showing a note-taking app interface being used through a keyboard" /></p><p>In the previous image, you can see the application, which only allows taking notes via the keyboard, which can be tedious, slow and boring. Therefore, we will use the speech-to-text control to improve quick note-taking.</p><h2 id="integrating-the-speechtotextbutton-control-into-the-application">Integrating the SpeechToTextButton Control into the Application</h2><p>The first thing you need to do to use the speech-to-text control is to follow the <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/first-steps-vs">Telerik .NET MAUI controls installation guide</a>. Once you have done that, add the following namespace in the <code>ContentPage</code> where you want to use the control:</p><pre class=" language-xml"><code class="prism  language-xml">xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"</code></pre><p>Next, add the control using the <code>RadSpeechToTextButton</code> tag where you want to place it; in our example, it will be located where the <strong>Editor Toolbar</strong> comment is:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadSpeechToTextButton</span>
    <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>SpeechButton<span class="token punctuation">"</span></span>
    <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>3<span class="token punctuation">"</span></span>
    <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
</code></pre><p>Since we will be using the microphone in the app for obtaining the transcription, you need to grant the <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/controls/speechtotextbutton/getting-started#required-permissions">required permissions according to the platform</a> to allow audio recording and voice recognition. For example, for Android, you need to add the following line to <code>AndroidManifest.xml</code>:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;</code></pre><p>The integration of the control provides a button with the necessary functionality to start the speech-to-text process:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/showing-the-button-that-enables-the-speech-to-text-functionality.gif?sfvrsn=8d2c43db_2" alt="Showing the button that enables the speech-to-text functionality, with the microphone activating automatically" /></p><p>In the image above, you can see that when the button to start recording is pressed, the microphone is automatically activated in the status bar (if it&rsquo;s the first execution, it will likely ask for microphone access), indicating that a recording process has started.</p><p>Now we need to handle the events or commands to obtain the transcription, which we will see next.</p><h2 id="available-events-and-commands-in-the-speech-to-text-control-for-.net-maui">Available Events and Commands in the Speech to Text Control for .NET MAUI</h2><p>The speech to text control has events and commands that we can use to react to different situations. For the events, we have the following available:</p><ul><li><code>SpeechRecognized</code>: This occurs when there is a successful speech recognition and includes an argument <code>SpeechRecognizerSpeechRecognizedEventArgs</code>, which contains the <code>FullText</code> obtained from the recognition and <code>FullTextConfidenceScore</code> indicating the confidence level of the recognition.</li><li><code>ErrorOccurred</code>: This occurs when there is an error in the recognition process, includes the argument <code>SpeechRecognizerErrorOccurredEventArgs</code>, which contains the <code>Message</code> property with the error message, the <code>Exception</code> associated with the error and <code>Handled</code> to determine if the error has been handled.</li><li><code>StateChanged</code>: This is fired as soon as there is a change in the state of the speech recognizer.</li></ul><p>On the other hand, we also have some commands that will allow us to handle events directly from the viewmodel if we need to, as is the case for us. To achieve this, we can modify the label of the <code>RadSpeechToTextButton</code> control by adding the commands <code>SpeechRecognizedCommand</code> and <code>ErrorOccurredCommand</code> as shown in the following example:</p><pre class=" language-xml"><code class="prism  language-xml"> <span class="token comment">&lt;!--  Editor Toolbar  --&gt;</span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border...</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>*, Auto, Auto, Auto<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        ...
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadSpeechToTextButton</span>
            <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>SpeechButton<span class="token punctuation">"</span></span>
            <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>3<span class="token punctuation">"</span></span>
            <span class="token attr-name">ErrorOccurredCommand</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding ErrorOccurredCommand}<span class="token punctuation">"</span></span>
            <span class="token attr-name">SpeechRecognizedCommand</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SpeechRecognizedCommand}<span class="token punctuation">"</span></span>
            <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>Next, we need to handle the commands from the viewmodel as seen below:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token preprocessor property">#<span class="token directive keyword">region</span> Speech Recognition Commands</span>

<span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">SpeechRecognized</span><span class="token punctuation">(</span>SpeechToTextButtonSpeechRecognizedCommandContext context<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    EditorText <span class="token operator">=</span> context<span class="token punctuation">.</span>FullText<span class="token punctuation">;</span>
    <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Speech recognized"</span><span class="token punctuation">,</span> <span class="token string">"#10B981"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token punctuation">[</span>RelayCommand<span class="token punctuation">]</span>
<span class="token keyword">private</span> <span class="token keyword">async</span> Task <span class="token function">ErrorOccurredAsync</span><span class="token punctuation">(</span>SpeechToTextButtonErrorOccurredCommandContext context<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Error occurred"</span><span class="token punctuation">,</span> <span class="token string">"#EF4444"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>Application<span class="token punctuation">.</span>Current<span class="token operator">?</span><span class="token punctuation">.</span>Windows<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">.</span>Page <span class="token keyword">is</span> Page page<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">await</span> page<span class="token punctuation">.</span><span class="token function">DisplayAlertAsync</span><span class="token punctuation">(</span><span class="token string">"Voice Input Error"</span><span class="token punctuation">,</span>
            $<span class="token string">"Unable to process voice input: {context.Message}"</span><span class="token punctuation">,</span>
            <span class="token string">"OK"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token preprocessor property">#<span class="token directive keyword">endregion</span></span>
</code></pre><p>In the previous code, you can see that the commands receive contexts similar to the arguments of the events. The first, <code>SpeechToTextButtonSpeechRecognizedCommandContext</code>, allows obtaining the <code>FullText</code> and <code>FullTextConfidenceScore</code> when there is speech recognition. The second, <code>SpeechToTextButtonErrorOccurredCommandContext</code>, contains the <code>Message</code> and <code>Exception</code> properties when there is an error in the speech recognition.</p><p>You can also see how <code>FullText</code> is assigned to the <code>EditorText</code> property, which is bound to the control of type <code>Editor</code>. This allows the transcription obtained to be displayed in the graphical interface, resulting in the following execution:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/live-demonstration-of-telerik-speech-to-text-control-for-maui.gif?sfvrsn=a3fc5485_2" alt="Live demonstration of Telerik’s Speech-to-Text control for .NET MAUI, enabling real-time voice transcription" /></p><p>Now we can obtain the transcription; however, there is a need for visual indicators that allow users to know what is happening in the application, and we can solve this through the states of the control. Let&rsquo;s see how.</p><h2 id="states-of-the-speech-to-text-control">States of the Speech-to-Text Control</h2><p>One thing that is appreciated as a developer is that Progress Telerik documentation is very clear regarding the architecture and lifecycle of the .NET MAUI SpeechToTextButton control, as can be seen in the following image:</p><p><img src="https://www.telerik.com/maui-ui/documentation/assets/0b2b21d54845c1079dac37312faab870/speechtotext-architecture.png" alt="Architecture and lifecycle of the SpeechToTextButton control" /></p><p>The diagram above shows us a series of states that we can detect thanks to the <code>StateChanged</code> event as seen below:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadSpeechToTextButton</span>
    <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>SpeechButton<span class="token punctuation">"</span></span>
    <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>3<span class="token punctuation">"</span></span>
    <span class="token attr-name">ErrorOccurredCommand</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding ErrorOccurredCommand}<span class="token punctuation">"</span></span>
    <span class="token attr-name">SpeechRecognizedCommand</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SpeechRecognizedCommand}<span class="token punctuation">"</span></span>
    <span class="token attr-name">StateChanged</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>OnStateChanged<span class="token punctuation">"</span></span>
    <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
</code></pre><p>In the code behind, we can invoke a method from the viewmodel that allows us to determine what to do with the detected state:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">OnStateChanged</span><span class="token punctuation">(</span><span class="token keyword">object</span> sender<span class="token punctuation">,</span> EventArgs e<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>sender <span class="token keyword">is</span> RadSpeechToTextButton button<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        MainThread<span class="token punctuation">.</span><span class="token function">BeginInvokeOnMainThread</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span>
        <span class="token punctuation">{</span>
            _viewModel<span class="token punctuation">.</span><span class="token function">UpdateButtonState</span><span class="token punctuation">(</span>button<span class="token punctuation">.</span>State<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>Within the viewmodel, we will compare the desired state using any of the states defined in the <code>Telerik.Maui.SpeechRecognizer.SpeechRecognizerState</code> enumeration.</p><p>For example, to react to state changes <code>Listening</code> and <code>Initializing</code>, the code would be as follows:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">UpdateButtonState</span><span class="token punctuation">(</span>Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>SpeechRecognizer<span class="token punctuation">.</span>SpeechRecognizerState state<span class="token punctuation">)</span>
<span class="token punctuation">{</span>        
    <span class="token keyword">switch</span> <span class="token punctuation">(</span>state<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>            
        <span class="token keyword">case</span> Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>SpeechRecognizer<span class="token punctuation">.</span>SpeechRecognizerState<span class="token punctuation">.</span>Listening<span class="token punctuation">:</span>
            <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Listening..."</span><span class="token punctuation">,</span> <span class="token string">"#2563EB"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">break</span><span class="token punctuation">;</span>
        <span class="token keyword">case</span> Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>SpeechRecognizer<span class="token punctuation">.</span>SpeechRecognizerState<span class="token punctuation">.</span>Initializing<span class="token punctuation">:</span>
            <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Initializing..."</span><span class="token punctuation">,</span> <span class="token string">"#F59E0B"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">break</span><span class="token punctuation">;</span>
        <span class="token keyword">default</span><span class="token punctuation">:</span>
            <span class="token function">UpdateStatus</span><span class="token punctuation">(</span><span class="token string">"Ready"</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">break</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>Finally, in the graphical interface code, we can add visual indicators that provide feedback to the user about the state of the control. In our example, we do this in the comment section <strong>Status Bar</strong>:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token comment">&lt;!--  Status Bar  --&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border</span>
    <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
    <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16,12<span class="token punctuation">"</span></span>
    <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#F3F4F6<span class="token punctuation">"</span></span>
    <span class="token attr-name">StrokeShape</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RoundRectangle 12<span class="token punctuation">"</span></span>
    <span class="token attr-name">StrokeThickness</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Auto, *, Auto<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Ellipse</span>
            <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding StatusColor}<span class="token punctuation">"</span></span>
            <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span>
            <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>
            <span class="token attr-name">WidthRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>        
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
            <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
            <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12,0,0,0<span class="token punctuation">"</span></span>
            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>14<span class="token punctuation">"</span></span>
            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding StatusText}<span class="token punctuation">"</span></span>
            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#374151<span class="token punctuation">"</span></span>
            <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
            <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span>
            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span>
            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding CharacterCount}<span class="token punctuation">"</span></span>
            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#9CA3AF<span class="token punctuation">"</span></span>
            <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>Once the previous code has been replaced, we will graphically see the state changes, to indicate to users that the component is ready to start transcription, if it is listening to speech or if speech has been recognized correctly:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/handling-the-state-validation-of-the-speech-to-text-control.gif?sfvrsn=4bfd00e8_2" alt="Handling the state validation of the Speech-to-Text control, providing user feedback about what is happening in the application" /></p><p>In the above image, you can see the state changes in action, according to the actions performed by the user on the speech to text control.</p><h2 id="conclusion">Conclusion</h2><p>Throughout this article, you have been able to learn about the SpeechToTextButton control from Telerik for .NET MAUI applications.</p><p>Implementing this type of component in your mobile applications can greatly simplify the friction that exists with users when it comes to entering lengthy or rapid text, something very trendy today with AI-based apps. I encourage you to try it out and help your users get the most out of your applications.</p><p>If you aren&rsquo;t already using Telerik UI for .NET MAUI, it comes with a free 30-day trial:</p><p><a target="_blank" href="https://www.telerik.com/try/ui-for-maui" class="Btn">Try Now</a></p>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:81ae8790-39c7-475d-9a30-6d8910a1d815</id>
    <title type="text">Getting Started with the BottomSheet Component for .NET MAUI</title>
    <summary type="text">If your mobile app needs a slide-up section to appear from the bottom of the screen, check out the .NET MAUI BottomSheet component.</summary>
    <published>2026-03-23T21:49:40Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/getting-started-bottomsheet-component-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">If your mobile app needs a slide-up section to appear from the bottom of the screen, check out the .NET MAUI BottomSheet component.</span></p><p>In some modern mobile applications, we can see a component called Bottom Sheet in action, which allows the user to slide a section up from the bottom of the application to display actions or information without changing the screen.</p><p>This type of component does not exist as part of the native .NET MAUI controls. Fortunately, the Progress Telerik suite of controls for .NET MAUI offers the <a target="_blank" href="https://www.telerik.com/maui-ui/bottomsheet">.NET MAUI BottomSheet</a> component, which we will analyze during this post. Let&rsquo;s get started!</p><h2 id="discovering-the-telerik-.net-maui-bottomsheet-component-for-.net-maui">Discovering the Telerik .NET MAUI BottomSheet Component for .NET MAUI</h2><p>We will explore different features of the Bottom Sheet component, for which I will show you a window created with XAML code that could well represent a section of a real application. Next, I will show you how to implement the Bottom Sheet control to display selection options to users in the same window.</p><h2 id="creating-an-example-project">Creating an Example Project</h2><p>Suppose we have a project that allows users to order food from restaurants through an application. For the creation of the XAML page, I have used different controls from the Telerik UI for .NET MAUI suite, which enable the quick creation of custom graphical interfaces:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid.RowDefinitions</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>RowDefinition</span> <span class="token attr-name">Height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.2*<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>RowDefinition</span> <span class="token attr-name">Height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.8*<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid.RowDefinitions</span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!--  Header Section  --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>VerticalStackLayout</span> <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>25,25,25,0<span class="token punctuation">"</span></span> <span class="token attr-name">Spacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
            <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span>
            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span>
            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>DELIVERY ADDRESS<span class="token punctuation">"</span></span>
            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>White<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid.ColumnDefinitions</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ColumnDefinition</span> <span class="token attr-name">Width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>*<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ColumnDefinition</span> <span class="token attr-name">Width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Auto<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid.ColumnDefinitions</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid.GestureRecognizers</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>TapGestureRecognizer</span> <span class="token attr-name">Tapped</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>OnAddressTapped<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid.GestureRecognizers</span><span class="token punctuation">&gt;</span></span>

            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>CurrentAddressLabel<span class="token punctuation">"</span></span>
                <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16<span class="token punctuation">"</span></span>
                <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>123 Main Street, City<span class="token punctuation">"</span></span>
                <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>White<span class="token punctuation">"</span></span>
                <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10,0,0,0<span class="token punctuation">"</span></span>
                <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>14<span class="token punctuation">"</span></span>
                <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>▼<span class="token punctuation">"</span></span>
                <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>White<span class="token punctuation">"</span></span>
                <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>

        <span class="token comment">&lt;!--  Search Bar  --&gt;</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadBorder</span>
            <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span>
            <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#6B5BAF<span class="token punctuation">"</span></span>
            <span class="token attr-name">CornerRadius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Auto,*<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                    <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0,0,10,0<span class="token punctuation">"</span></span>
                    <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16<span class="token punctuation">"</span></span>
                    <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span>
                    <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadEntry</span>
                    <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>StoreSearchEntry<span class="token punctuation">"</span></span>
                    <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                    <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Transparent<span class="token punctuation">"</span></span>
                    <span class="token attr-name">BorderThickness</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
                    <span class="token attr-name">ClearButtonVisibility</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>WhileEditing<span class="token punctuation">"</span></span>
                    <span class="token attr-name">Placeholder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Search a restaurant or dish<span class="token punctuation">"</span></span>
                    <span class="token attr-name">PlaceholderColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#B8B0D0<span class="token punctuation">"</span></span>
                    <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>White<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadBorder</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>VerticalStackLayout</span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!--  Store List  --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadBorder</span>
        <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
        <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0,10,0,0<span class="token punctuation">"</span></span>
        <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#F2F1F6<span class="token punctuation">"</span></span>
        <span class="token attr-name">CornerRadius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>25,25,0,0<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadCollectionView</span>
            <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>StoresCollection<span class="token punctuation">"</span></span>
            <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>15<span class="token punctuation">"</span></span>
            <span class="token attr-name">SelectionChanged</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>OnStoreSelected<span class="token punctuation">"</span></span>
            <span class="token attr-name">SelectionMode</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Single<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadCollectionView.ItemsLayout</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>CollectionViewLinearLayout</span> <span class="token attr-name">ItemSpacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>15<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadCollectionView.ItemsLayout</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadCollectionView.ItemTemplate</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>DataTemplate</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border</span>
                        <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
                        <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>White<span class="token punctuation">"</span></span>
                        <span class="token attr-name">StrokeShape</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RoundRectangle 15<span class="token punctuation">"</span></span>
                        <span class="token attr-name">StrokeThickness</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border.Shadow</span><span class="token punctuation">&gt;</span></span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Shadow</span>
                                <span class="token attr-name">Brush</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#CFD0D4<span class="token punctuation">"</span></span>
                                <span class="token attr-name">Opacity</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0.5<span class="token punctuation">"</span></span>
                                <span class="token attr-name">Radius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span>
                                <span class="token attr-name">Offset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>5,5<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border.Shadow</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span> <span class="token attr-name">RowDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>150,Auto<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                            <span class="token comment">&lt;!--  Store Header Image  --&gt;</span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid.RowDefinitions</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>RowDefinition</span> <span class="token attr-name">Height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.6*<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>RowDefinition</span> <span class="token attr-name">Height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.4*<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid.RowDefinitions</span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid.ColumnDefinitions</span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ColumnDefinition</span> <span class="token attr-name">Width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.4*<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ColumnDefinition</span> <span class="token attr-name">Width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.2*<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ColumnDefinition</span> <span class="token attr-name">Width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.4*<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid.ColumnDefinitions</span><span class="token punctuation">&gt;</span></span>

                                <span class="token comment">&lt;!--  Header Image  --&gt;</span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Image</span>
                                    <span class="token attr-name">Grid.RowSpan</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">Grid.ColumnSpan</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>3<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">Aspect</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>AspectFill<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">Source</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Header}<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

                                <span class="token comment">&lt;!--  Logo with gradient border  --&gt;</span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span>
                                    <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10,0,0,0<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>70<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Start<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>End<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">WidthRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>70<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border</span>
                                        <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>65<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">StrokeShape</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Ellipse<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">StrokeThickness</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>3<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">WidthRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>65<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border.Stroke</span><span class="token punctuation">&gt;</span></span>
                                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>LinearGradientBrush</span> <span class="token attr-name">EndPoint</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0,1<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>GradientStop</span> <span class="token attr-name">Offset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0.0<span class="token punctuation">"</span></span> <span class="token attr-name">Color</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#FEFEEF<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>GradientStop</span> <span class="token attr-name">Offset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0.25<span class="token punctuation">"</span></span> <span class="token attr-name">Color</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#EBD570<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>GradientStop</span> <span class="token attr-name">Offset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0.5<span class="token punctuation">"</span></span> <span class="token attr-name">Color</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#FF94C3<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>GradientStop</span> <span class="token attr-name">Offset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0.75<span class="token punctuation">"</span></span> <span class="token attr-name">Color</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#A573E4<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>GradientStop</span> <span class="token attr-name">Offset</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1.0<span class="token punctuation">"</span></span> <span class="token attr-name">Color</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#A9E2EE<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>LinearGradientBrush</span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border.Stroke</span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Image</span>
                                            <span class="token attr-name">Aspect</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>AspectFill<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">Source</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Logo}<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>

                                <span class="token comment">&lt;!--  Rating Badge  --&gt;</span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border</span>
                                    <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0,0,10,10<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10,5<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#F8F8F7<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>35<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">StrokeShape</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RoundRectangle 10<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">StrokeThickness</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>End<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">WidthRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>70<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>HorizontalStackLayout</span>
                                        <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">Spacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>8<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>14<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>⭐<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                                            <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>14<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Rating}<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Black<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>HorizontalStackLayout</span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>

                            <span class="token comment">&lt;!--  Store Info  --&gt;</span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>VerticalStackLayout</span>
                                <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                                <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>15<span class="token punctuation">"</span></span>
                                <span class="token attr-name">Spacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>8<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                                    <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>18<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Name}<span class="token punctuation">"</span></span>
                                    <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Black<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>*,*,*<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                                        <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>13<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Minimum, StringFormat=<span class="token punctuation">'</span>${0} min<span class="token punctuation">'</span>}<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#666666<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                                        <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>13<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding ServiceFee, StringFormat=<span class="token punctuation">'</span>Fee: ${0}<span class="token punctuation">'</span>}<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#666666<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                                        <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>13<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>End<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding DeliveryTime}<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#666666<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>VerticalStackLayout</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>DataTemplate</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadCollectionView.ItemTemplate</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadCollectionView</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadBorder</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>The result is a beautiful graphical interface that showcases some fictional restaurants, along with additional controls like a search bar and a physical address selector:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/screenshot-of-a-food-ordering-stores-page-built-using-telerik-ui-components-for-net-maui.png?sfvrsn=7724c601_2" alt="Screenshot of a food ordering stores page built using Telerik UI components for .NET MAUI" /></p><p>In the screenshot above, you can see some Telerik components used, such as the following:</p><ul><li><code>RadEntry</code>: For the store search bar</li><li><code>RadBorder</code>: To enhance the appearance of the search bar and list items</li><li><code>RadCollection</code>: To display the list of stores</li></ul><p>At the top of the app, I have placed a fictional address below the text <strong>Delivery Address</strong>. Ideally, users should be able to select a different delivery address if needed without leaving the current screen. This is an excellent use case for a Bottom Sheet.</p><h2 id="getting-to-know-the-telerik-bottomsheet-component">Getting to Know the Telerik BottomSheet Component</h2><p>To implement the Bottom Sheet component, it&rsquo;s essential to understand that it consists of three parts that we can configure:</p><ul><li><strong>BottomSheet Main Content</strong>: Container for the graphic content that will be visible before displaying the Bottom Sheet.</li><li><strong>BottomSheet Content</strong>: Content that fills the Bottom Sheet and that we will show as options or additional information to the user.</li><li><strong>BottomSheet Handle</strong>: A visual cue that indicates to the user that they can drag the Bottom Sheet.</li></ul><p>You can see the location of each of these parts graphically below:</p><p><img src="https://www.telerik.com/maui-ui/documentation/assets/e969b13abd4921187e78b87b013681f9/bottomsheet-visual-structure.png" alt="Visual structure of a Telerik BottomSheet control for .NET MAUI" /></p><p>Now that we have this information, let&rsquo;s proceed to add a Bottom Sheet to the project.</p><h2 id="adding-the-bottomsheet-component-to-a-.net-maui-project">Adding the BottomSheet Component to a .NET MAUI Project</h2><p>Once we are familiar with the main parts of the Bottom Sheet control, the next step is to migrate the existing UI content into the <strong>BottomSheet Main Content</strong> section, using the <code>Content</code> property as follows:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadBottomSheet</span> <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>AddressBottomSheet<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadBottomSheet.Content</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span><span class="token punctuation">&gt;</span></span>
            ...
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
     <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadBottomSheet.Content</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadBottomSheet</span><span class="token punctuation">&gt;</span></span>

</code></pre><p>The above will determine the content over which the Bottom Sheet will appear. Next, we need to specify the <code>BottomSheetContent</code> tag, where we will define the content that will be shown to the user when the Bottom Sheet appears:</p><pre class=" language-xml"><code class="prism  language-xml">    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadBottomSheet</span> <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>AddressBottomSheet<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        ...
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadBottomSheet.BottomSheetContent</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span>
                <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>20,20,20,60<span class="token punctuation">"</span></span>
                <span class="token attr-name">RowDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Auto,Auto,*,Auto<span class="token punctuation">"</span></span>
                <span class="token attr-name">RowSpacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>15<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>

                <span class="token comment">&lt;!--  Header  --&gt;</span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>*,Auto<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>VerticalStackLayout</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                            <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span>
                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>22<span class="token punctuation">"</span></span>
                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span> Delivery Address<span class="token punctuation">"</span></span>
                            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#333333<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                            <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0,5,0,0<span class="token punctuation">"</span></span>
                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>13<span class="token punctuation">"</span></span>
                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Select or add a new delivery address<span class="token punctuation">"</span></span>
                            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#888888<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>VerticalStackLayout</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadTemplatedButton</span>
                        <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                        <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Transparent<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Clicked</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>OnCloseBottomSheet<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>✕<span class="token punctuation">"</span></span>
                        <span class="token attr-name">CornerRadius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>20<span class="token punctuation">"</span></span>
                        <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>20<span class="token punctuation">"</span></span>
                        <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>40<span class="token punctuation">"</span></span>
                        <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#666666<span class="token punctuation">"</span></span>
                        <span class="token attr-name">WidthRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>40<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>

                <span class="token comment">&lt;!--  Search Address  --&gt;</span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadBorder</span>
                    <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                    <span class="token attr-name">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span>
                    <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#EAEAEA<span class="token punctuation">"</span></span>
                    <span class="token attr-name">CornerRadius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Auto,*<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                            <span class="token attr-name">Margin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0,0,10,0<span class="token punctuation">"</span></span>
                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16<span class="token punctuation">"</span></span>
                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span>
                            <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadEntry</span>
                            <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>AddressSearchEntry<span class="token punctuation">"</span></span>
                            <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                            <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Transparent<span class="token punctuation">"</span></span>
                            <span class="token attr-name">Placeholder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Search your addresses...<span class="token punctuation">"</span></span>
                            <span class="token attr-name">PlaceholderColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#999999<span class="token punctuation">"</span></span>
                            <span class="token attr-name">BorderThickness</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0<span class="token punctuation">"</span></span>
                            <span class="token attr-name">ClearButtonVisibility</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>WhileEditing<span class="token punctuation">"</span></span>
                            <span class="token attr-name">TextChanged</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>OnAddressSearchTextChanged<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadBorder</span><span class="token punctuation">&gt;</span></span>

                <span class="token comment">&lt;!--  Address List --&gt;</span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadCollectionView</span>
                    <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>AddressesCollectionView<span class="token punctuation">"</span></span>
                    <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span>
                    <span class="token attr-name">SelectionChanged</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>OnAddressSelectionChanged<span class="token punctuation">"</span></span>
                    <span class="token attr-name">SelectionMode</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Single<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadCollectionView.ItemsLayout</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>CollectionViewLinearLayout</span> <span class="token attr-name">ItemSpacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadCollectionView.ItemsLayout</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadCollectionView.ItemTemplate</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>DataTemplate</span><span class="token punctuation">&gt;</span></span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border</span><span class="token style-attr language-css"><span class="token attr-name"> <span class="token attr-name">Style</span></span><span class="token punctuation">="</span><span class="token attr-value"><span class="token punctuation">{</span>StaticResource AddressItemStyle<span class="token punctuation">}</span></span><span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Grid</span> <span class="token attr-name">ColumnDefinitions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>*,Auto<span class="token punctuation">"</span></span> <span class="token attr-name">ColumnSpacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                    <span class="token comment">&lt;!--  Address Details  --&gt;</span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>VerticalStackLayout</span> <span class="token attr-name">Spacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span> <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                                            <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>15<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Label}<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#333333<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>13<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">LineBreakMode</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>TailTruncation<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding FullAddress}<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#888888<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>VerticalStackLayout</span><span class="token punctuation">&gt;</span></span>

                                    <span class="token comment">&lt;!--  Selection Indicator  --&gt;</span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Border</span>
                                        <span class="token attr-name">Grid.Column</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SelectionColor}<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>24<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">Stroke</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SelectionBorderColor}<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">StrokeShape</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RoundRectangle 12<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">StrokeThickness</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>2<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>
                                        <span class="token attr-name">WidthRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>24<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
                                            <span class="token attr-name">FontSize</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>14<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">HorizontalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding CheckMark}<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>White<span class="token punctuation">"</span></span>
                                            <span class="token attr-name">VerticalOptions</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>
                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>
                            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Border</span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>DataTemplate</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadCollectionView.ItemTemplate</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadCollectionView</span><span class="token punctuation">&gt;</span></span>

                <span class="token comment">&lt;!--  Action Buttons  --&gt;</span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>VerticalStackLayout</span> <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>3<span class="token punctuation">"</span></span> <span class="token attr-name">Spacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadButton</span>
                        <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>SelectAddressButton<span class="token punctuation">"</span></span>
                        <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#FB7647<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Clicked</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>OnSelectAddressClicked<span class="token punctuation">"</span></span>
                        <span class="token attr-name">CornerRadius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span>
                        <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span>
                        <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>54<span class="token punctuation">"</span></span>
                        <span class="token attr-name">IsEnabled</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>False<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Select Address<span class="token punctuation">"</span></span>
                        <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>White<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadButton</span>
                        <span class="token attr-name">BackgroundColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#4F3F9B<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Clicked</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>OnAddNewAddressClicked<span class="token punctuation">"</span></span>
                        <span class="token attr-name">CornerRadius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span>
                        <span class="token attr-name">FontAttributes</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Bold<span class="token punctuation">"</span></span>
                        <span class="token attr-name">HeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>54<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Add new address<span class="token punctuation">"</span></span>
                        <span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>White<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>VerticalStackLayout</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Grid</span><span class="token punctuation">&gt;</span></span>            
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadBottomSheet.BottomSheetContent</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadBottomSheet</span><span class="token punctuation">&gt;</span></span>        
</code></pre><p>With the above code, we have prepared the Bottom Sheet content to be displayed to the user when we indicate it.</p><h2 id="showing-the-bottomsheet-to-the-user">Showing the BottomSheet to the User</h2><p>Once we have the content of the Bottom Sheet ready, the next step is to display it.</p><p>There are several ways to achieve this; we will use the method <code>GoToBottomSheetState</code>, which allows for transitioning to a specific state. A state refers to how much screen space the Bottom Sheet will occupy, with possible values being <code>Hidden</code> (default), <code>Minimal</code> (25%), <code>Partial</code> (50%) and <code>Full</code> (90%). It is also possible to create <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/controls/bottomsheet/configuration#custom-states">custom states</a>.</p><p>Knowing the above, in my example I will use the <code>TapGestureRecognizer</code>, which is part of the container that displays the current address, to show the Bottom Sheet from there:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">OnAddressTapped</span><span class="token punctuation">(</span><span class="token keyword">object</span> sender<span class="token punctuation">,</span> EventArgs e<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
   AddressBottomSheet<span class="token punctuation">.</span><span class="token function">GoToBottomSheetState</span><span class="token punctuation">(</span>BottomSheetState<span class="token punctuation">.</span>FullState<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>In the same way that the Bottom Sheet can be shown at will, it can also be hidden using the same method, <code>GoToBottomSheetState</code>:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">OnCloseBottomSheet</span><span class="token punctuation">(</span><span class="token keyword">object</span> sender<span class="token punctuation">,</span> EventArgs e<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
   AddressBottomSheet<span class="token punctuation">.</span><span class="token function">GoToBottomSheetState</span><span class="token punctuation">(</span>BottomSheetState<span class="token punctuation">.</span>HiddenState<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>The execution of the above changes results in the following:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/bottomsheet-control-in-action-allowing-users-to-select-a-different-delivery-address-for-an-order.gif?sfvrsn=2e2648cc_2" alt="BottomSheet control in action, allowing users to select a different delivery address for an order" /></p><p>In the image above, you can see how it is possible to select a different address thanks to the use of the Bottom Sheet, with a spectacular appearance, all without leaving the current window.</p><h2 id="customizing-the-bottom-sheet">Customizing the Bottom Sheet</h2><p>The Telerik BottomSheet control for .NET MAUI offers several properties that allow for the customization of the control. For example, the property <code>Width</code> allows you to specify the horizontal space that the Bottom Sheet will occupy, either through an absolute value or a percentage:</p><p><img src="https://www.telerik.com/maui-ui/documentation/assets/857c771af2dd2af7a4d8c510d3ddd8a0/bottomsheet-width.gif" alt="Demonstration of horizontal size adjustment of the Bottom Sheet using the Width property" /></p><p>Similarly, if you want to prevent the user from dragging up or down on the BottomSheet Handle, you can configure the property <code>IsSwipeEnabled</code> with a value <code>false</code>.</p><p>In addition, it is also possible to modify the animation of the Bottom Sheet, enabling or disabling it with the property <code>IsAnimationEnabled</code>, and adjusting both the duration of the animation and the easing function used through the properties <code>AnimationDuration</code> and <code>AnimationEasing</code>.</p><p>You can also change features such as the border, corner radius and background color of the Bottom Sheet through the property <code>BottomSheetContentStyle</code>. Additionally, you can modify the properties of the BottomSheet Handle using the property <code>HandleStyle</code>.</p><p>Below, I show you an example of the aforementioned properties applied to the Bottom Sheet:</p><pre class=" language-xml"><code class="prism  language-xml">
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ContentPage...</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ContentPage.Resources</span><span class="token punctuation">&gt;</span></span>
        <span class="token comment">&lt;!--  BottomSheet Content Style  --&gt;</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Style</span> <span class="token attr-name"><span class="token namespace">x:</span>Key</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>BottomSheetContentStyle<span class="token punctuation">"</span></span> <span class="token attr-name">TargetType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>telerik:BottomSheetContentView<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token style language-css">
            &lt;Setter Property=<span class="token string">"BackgroundColor"</span> Value=<span class="token string">"#F7F7F7"</span> /&gt;
            &lt;Setter Property=<span class="token string">"CornerRadius"</span> Value=<span class="token string">"25,25,0,0"</span> /&gt;
            &lt;Setter Property=<span class="token string">"BorderColor"</span> Value=<span class="token string">"#4F3F9B"</span> /&gt;
            &lt;Setter Property=<span class="token string">"BorderThickness"</span> Value=<span class="token string">"5"</span> /&gt;
        </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Style</span><span class="token punctuation">&gt;</span></span>

        <span class="token comment">&lt;!--  BottomSheet Handle Style  --&gt;</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Style</span> <span class="token attr-name"><span class="token namespace">x:</span>Key</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>HandleStyle<span class="token punctuation">"</span></span> <span class="token attr-name">TargetType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>telerik:BottomSheetHandle<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token style language-css">
            &lt;Setter Property=<span class="token string">"BackgroundColor"</span> Value=<span class="token string">"#4F3F9B"</span> /&gt;
            &lt;Setter Property=<span class="token string">"HeightRequest"</span> Value=<span class="token string">"5"</span> /&gt;
            &lt;Setter Property=<span class="token string">"WidthRequest"</span> Value=<span class="token string">"60"</span> /&gt;
            &lt;Setter Property=<span class="token string">"CornerRadius"</span> Value=<span class="token string">"3"</span> /&gt;
        </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Style</span><span class="token punctuation">&gt;</span></span>
        ...
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ContentPage.Resources</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadBottomSheet</span>
        <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>AddressBottomSheet<span class="token punctuation">"</span></span>
        <span class="token attr-name">AnimationDuration</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>300<span class="token punctuation">"</span></span>
        <span class="token attr-name">AnimationEasing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{x:Static Easing.CubicOut}<span class="token punctuation">"</span></span>
        <span class="token attr-name">BottomSheetContent</span><span class="token style-attr language-css"><span class="token attr-name"><span class="token attr-name">Style</span></span><span class="token punctuation">="</span><span class="token attr-value"><span class="token punctuation">{</span>StaticResource BottomSheetContentStyle<span class="token punctuation">}</span></span><span class="token punctuation">"</span></span>
        <span class="token attr-name">BottomSheetContentWidth</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>100%<span class="token punctuation">"</span></span>
        <span class="token attr-name">Handle</span><span class="token style-attr language-css"><span class="token attr-name"><span class="token attr-name">Style</span></span><span class="token punctuation">="</span><span class="token attr-value"><span class="token punctuation">{</span>StaticResource HandleStyle<span class="token punctuation">}</span></span><span class="token punctuation">"</span></span>
        <span class="token attr-name">IsAnimationEnabled</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>True<span class="token punctuation">"</span></span>
        <span class="token attr-name">IsSwipeEnabled</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>True<span class="token punctuation">"</span></span>
        <span class="token attr-name">State</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Hidden<span class="token punctuation">"</span></span>
        <span class="token attr-name">StateChanging</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>OnBottomSheetStateChanging<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        ...
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadBottomSheet</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ContentPage</span><span class="token punctuation">&gt;</span></span>    
</code></pre><p>The result of executing with the previous changes applied provides greater customization of the Bottom Sheet:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/customization-of-the-bottom-sheet-and-the-bottom-sheet-handle.png?sfvrsn=96d75829_2" alt="Customization of the Bottom Sheet and the Bottom Sheet handle" /></p><p>With this, we achieve a visual improvement that better centers the user on the content of the Bottom Sheet.</p><h2 id="conclusion">Conclusion</h2><p>Throughout this article, you have learned about the BottomSheet component of the Telerik UI for .NET MAUI control suite, understanding its purpose and how to customize it to show users additional options without leaving the current screen.</p><p>Undoubtedly, adding this type of component to your applications can enhance the user experience by allowing them to perform quick actions or obtain information easily.</p><p>Want to try this out for yourself? Telerik UI for Blazor comes with a free 30-day trial. </p><p><a href="https://www.telerik.com/try/ui-for-maui" target="_blank" class="Btn">Download Now</a></p>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:5b2a3c79-efa5-4bc4-b24c-1cd5b9ea13e5</id>
    <title type="text">Accessibility (A11y) in .NET MAUI: What It Is and How to Implement It</title>
    <summary type="text">It’s time to add accessibility into the early stages of your .NET MAUI development cycle. The POUR principles can help.</summary>
    <published>2026-03-16T18:26:50Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/accessibility-net-maui-what-how-to-implement"/>
    <content type="text"><![CDATA[<p><span class="featured">It&rsquo;s time to add accessibility into the early stages of your .NET MAUI development cycle. The POUR principles can help.</span></p><p>Developing applications that can be used by everyone is a goal that any app should keep in mind. When I say &ldquo;for everyone,&rdquo; I mean that our applications should be able to communicate a clear and understandable purpose, so that people with or without disabilities can use them without issues. In other words, it&rsquo;s not just about &ldquo;making it work,&rdquo; nor about limiting it to a single way of use (such as only being understandable if you can read the buttons).</p><p>You&rsquo;ve probably heard the term <strong>A11y,</strong> and maybe you&rsquo;ve stopped to think&hellip; What does it mean?  A11y refers to the <strong>accessibility</strong> of our applications. While it&rsquo;s much more common to hear this term in the web space, mobile applications should also take it into account to offer a better product.</p><p>In this article, you&rsquo;ll learn more about accessibility, some guidelines you can follow to apply it correctly in <strong>.NET MAUI</strong>, the aspects you should start paying attention to and why <strong>A11y is not an extra</strong>, but a fundamental part of the quality of a well-built application.</p><h2 id="let’s-talk-more-about-a11y">Let&rsquo;s Talk More About A11y</h2><p><strong>A11y</strong> is an abbreviated form of the word <strong>accessibility</strong>, and its goal is to allow people with or without visual, auditory, motor or cognitive disabilities to use your apps. A11Y is a type of abbreviation very common in technology, and it is known as a <strong>numeronym.</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/01_accessibilitysample.png?sfvrsn=2429b72_2" alt="A c c e s s i b i l i t y : Diagram showing why ‘Accessibility’ is abbreviated as A11y, with 11 letters between A and Y." /></p><p>It works as follows:</p><ul><li><strong>A:</strong> is the first letter of the word.</li><li><strong>11:</strong> is the number of characters that come after the first letter and before the last one. In Accessibility, specifically in &ldquo;ccessibilit,&rdquo; there are 11 letters.</li><li><strong>Y:</strong> is the last letter of the word.</li></ul><p>That&rsquo;s why it is abbreviated as: <strong>A11y.</strong> This method makes it much more convenient to write long terms in a faster way and helps standardize lengthy terminology.</p><h2 id="how-can-we-apply-a11y-in-our-apps">How Can We Apply A11y in Our Apps?</h2><p>To implement this in our applications, there are accessibility guidelines such as <strong>WCAG,</strong> which instruct us on how to adapt the tools that mobile devices already provide so they can work together with our apps.</p><p>The <strong><a target="_blank" href="https://www.w3.org/TR/WCAG22/">Web Content Accessibility Guidelines (WCAG)</a></strong> are a set of international guidelines created by the <strong>World Wide Web Consortium (W3C).</strong> Although web is part of their name, I always recommend applying these practices to all types of applications, including mobile. Our users will thank us for it.</p><p>In fact, the official documentation states the following:</p><blockquote><p>&ldquo;These guidelines address accessibility of web content on any kind of device (including desktops, laptops, kiosks, and mobile devices).&rdquo;</p></blockquote><p>The WCAG are built on <strong>four fundamental principles,</strong> known as <strong>POUR.</strong> WCAG defines what an application must comply with to be accessible, while POUR helps us understand how to think about accessibility from a development perspective.</p><p>These four criteria that make up <strong>POUR</strong> are:</p><ul><li><strong>P</strong>erceivable</li><li><strong>O</strong>perable</li><li><strong>U</strong>nderstandable</li><li><strong>R</strong>obust</li></ul><p>Let&rsquo;s take a closer look at <strong>POUR</strong>&mdash;what each principle means and some examples of how we can translate them into our <strong>.NET MAUI</strong> applications:</p><h2 id="perceivable">Perceivable</h2><p>This principle indicates that all the information in the app (including text and UI components) must be <strong>perceivable by the user</strong>, regardless of how they interact with the device. In other words, our app should not be based solely on visual information.</p><p>This is especially important for users who:</p><ul><li>Use screen readers such as <strong>TalkBack</strong> or <strong>VoiceOver</strong></li><li>Have low vision or use larger text sizes</li></ul><p>In <strong>.NET MAUI</strong>, we have <strong>SemanticProperties</strong>, which help us a lot with this aspect.</p><p> Semantic properties are the Microsoft-recommended approach in .NET MAUI to provide accessibility values in applications. This allows us to add a description to our visual elements so that they can be read by the screen reader.</p><p>Additionally, I recommend exploring <strong><a target="_blank" href="https://www.telerik.com/blogs/exploring-semanticorderview-net-maui-community-toolkit">SemanticOrderView</a></strong>. While the individual reading of each visual element is important, being able to provide the user with a <strong>reading order</strong> so that this reading is coherent greatly enhances a good user experience. For this, we can use <strong>SemanticOrderView</strong> from the <strong>.NET MAUI Community Toolkit</strong>.</p><p>Let&rsquo;s explore some examples of implementing the Percievable principle in .NET MAUI:</p><h3 id="alternative-text-for-images-and-icons">Alternative Text for Images and Icons</h3><p>Images and icons are very common in mobile apps, but for a screen reader, an image without a description is <strong>100% invisible</strong>. That&rsquo;s why it&rsquo;s recommended to tell the screen reader that there is something there and <strong>what it should read</strong>.</p><p>In the following example, you can see the <strong>warning.png</strong> image used in the UI. When navigating the app with VoiceOver or TalkBack, this image will be announced as &ldquo;Warning icon.&rdquo; For this reason, I recommend being as specific as possible when defining its description.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Image Source="warning.png"
 SemanticProperties.Description="Warning icon" /&gt;
</code></pre><h3 id="what-about-decorative-images">What About Decorative Images?</h3><p>Not all images provide information. In these cases, we can <strong>remove them from the accessibility tree</strong> so the screen reader ignores them (meaning it won&rsquo;t read them):</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Image Source="divider.png"
 AutomationProperties.IsInAccessibleTree="False" /&gt;
</code></pre><p>This helps keep the experience cleaner and prevents the screen reader from reading unnecessary elements.</p><h3 id="headings">Headings</h3><p>Screen readers don&rsquo;t just &ldquo;read in order&rdquo; and stop there; they also allow users to <strong>navigate by sections</strong>. For this reason, it&rsquo;s important to mark titles or main sections as <strong>semantic headings</strong>.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="Payment Settings" 
 FontSize="24" 
 SemanticProperties.HeadingLevel="Level1" /&gt;
</code></pre><p>This way, the screen reader recognizes this element as a heading and makes navigation within the screen much easier.</p><h3 id="supporting-scalable-text">Supporting Scalable Text</h3><p>In addition to screen readers, there is also a significant number of users with low vision. You may have noticed that some people use very large text on their phones; that&rsquo;s probably why.</p><p>As developers, we can contribute to making our app more accessible by allowing it to adapt to the text size users feel most comfortable with.</p><p>For this, in .NET MAUI we have <strong>FontAutoScalingEnabled</strong>, a property that allows the text in our app to automatically scale according to the system preferences.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="Payment Settings" 
 FontSize="24" 
 FontAutoScalingEnabled="True" /&gt;
</code></pre><p>With this, if the user increases the text size from the device settings, the Label will scale accordingly, improving readability and aligning with the <strong>Perceivable</strong> principle.</p><h2 id="operable">Operable</h2><p>The Operable principle states that users must be able to interact with the app without difficulty, regardless of the way they use the device.</p><p>In other words, not all users interact in the same way. Some use screen readers, others use a keyboard or assisted navigation. For this reason, the app should not rely solely on complex gestures or interactions that do not provide a clear alternative.</p><p>In mobile applications, this principle basically translates into:</p><ul><li>Easy-to-tap controls</li><li>Clear and predictable navigation</li><li>Avoiding interactions that require extreme precision</li></ul><p>In .NET MAUI, many of these best practices can be applied directly using the components we already work with. Let&rsquo;s see NET MAUI some Operable examples we can apply:</p><h3 id="appropriate-size-for-interactive-elements">Appropriate Size for Interactive Elements</h3><p>A very common problem is having <strong>icons or buttons that are too small</strong>, which limits interaction and can make the app difficult&mdash;or even impossible&mdash;to use for some users.</p><p>For this reason, it is recommended to respect minimum sizes for interactive elements:</p><ul><li><p><strong>iOS:</strong> minimum <strong>44 &times; 44 pt</strong><br />This recommendation comes from Apple&rsquo;s Human Interface Guidelines, where this minimum size is established for interactive elements such as buttons or tappable icons.</p></li><li><p><strong>Android</strong>: minimum <strong>48 &times; 48 dp</strong><br />On Android, this recommendation comes from the Android Accessibility Guidelines and Material Design.</p></li></ul><p>In .NET MAUI, we can apply this easily, for example:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button Text="Continue" 
 HeightRequest="48" 
 Padding="16,12" /&gt;
</code></pre><p>Or for icon ImageButton:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;ImageButton Source="close.png" 
 WidthRequest="48" 
 HeightRequest="48" 
 Padding="12" 
 SemanticProperties.Description="Close" /&gt;
</code></pre><h2 id="understandable">Understandable</h2><p>This principle states that the information and interactions within our app must be <strong>easy to understand</strong>.</p><p>Why is this important?</p><ul><li>Not all users have the same technical level.</li><li>Some may have cognitive difficulties.</li><li>Others are simply using the app for the first time.</li></ul><p>In mobile applications, this principle mainly translates into:</p><ul><li>Clear and direct text</li><li>Consistent navigation</li><li>Predictable actions</li><li>Error messages that explain what happened and what to do next</li></ul><p>Some examples of Understandable in .NET MAUI:</p><h3 id="clear-language-in-text-and-labels">Clear Language in Text and Labels</h3><p>Avoid ambiguous or overly technical texts (I&rsquo;ve literally seen &ldquo;state error&rdquo; in apps &hellip; that should not happen), especially in buttons and important messages.</p><p>For example, for a save button, use text that clearly describes the action:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button Text="Save changes" /&gt;
</code></pre><p>Once the save action is executed, if an error occurs, <strong>don&rsquo;t leave the user guessing or hanging</strong>. Tell them exactly what happened.</p><p>❌ Saving changes failed</p><p>✅ The name field cannot contain special characters</p><p>The idea is for the user to understand what happened and what the next step is, without having to interpret technical messages.</p><h2 id="robust">Robust</h2><p>This principle states that the app must be <strong>robust enough</strong> to work correctly across different environments or devices. In other words, the app should continue to work when:</p><ul><li>It runs on different versions of the operating system</li><li>It is used with screen readers such as TalkBack or VoiceOver</li><li>It is used across different platforms</li><li>It adapts to different screen sizes (small, medium and large) without affecting usability or content clarity</li></ul><p>An example of the Robust principle in <strong>.NET MAUI</strong> is the use of <strong>OnPlatform</strong>.</p><h3 id="onplatform">OnPlatform</h3><p>Although .NET MAUI abstracts many platform differences&mdash;and personally, I try to use OnPlatform as little as possible to keep maintenance easier across Android and iOS, always looking for visual elements that give me the same result&mdash;in some cases, Android and iOS behave differently, and using it becomes necessary.</p><p>If you run into that situation, you can use OnPlatform to keep the behavior on both platforms exactly how you want it:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button Text="Continue" 
 HeightRequest="{OnPlatform iOS=44, Android=48}" 
 Padding="{OnPlatform iOS='16,12', Android='16,14'}" /&gt;
</code></pre><p>This way, you respect each platform&rsquo;s recommendations while keeping an accessible and consistent experience, aligned with the <strong>Robust</strong> principle.</p><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, we talked about <strong>A11y</strong> and why accessibility should be part of how we build mobile apps with <strong>.NET MAUI,</strong> not something added at the end. By understanding the <strong>POUR principles</strong> we saw how accessibility can be applied through small, intentional UI decisions.</p><p>From making content perceivable and interactions operable, to keeping things understandable and keeping our apps robust across platforms, each choice helps create a better experience for more users.</p><p>Remember: users may not know what A11Y is, but they definitely feel it when an app is accessible. </p><p>See you in the next article! &zwj;♀️✨</p><aside><hr data-sf-ec-immutable="" /><div class="row"><div class="col-4 u-normal-full u-small-mb0"><h4 class="u-fs20 u-fw5 u-lh125 u-mb0">The Next Development Discipline Is ADD</h4></div><div class="col-8"><p class="u-fs16 u-mb0"><a target="_blank" href="https://www.telerik.com/blogs/next-development-discipline-add">Accessibility-Driven Development turns WCAG into a discipline.</a> With the EU Accessibility Act as the deadline, ADD is the next discipline to drive quality.</p></div></div></aside>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:d14754de-590c-4eae-a95c-5390383b1082</id>
    <title type="text">5 UX Tips for .NET MAUI Developers</title>
    <summary type="text">Following these five UX tips as a .NET MAUI developer can help keep your app user-friendly and polished.</summary>
    <published>2026-03-10T16:30:34Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/5-ux-tips-net-maui-developers"/>
    <content type="text"><![CDATA[<p><span class="featured">Following these five UX tips as a .NET MAUI developer can help keep your app user-friendly and polished.</span></p><p>Creating a pleasant app experience doesn&rsquo;t always depend on having the most complex designs, the most harmonious colors, or the best user experience (UX). Obviously, all of this carries a lot of weight, but many times that whole system can be overshadowed by the lack of small details that can make a big difference between an average app and one that feels fast and familiar for your user.</p><p>As developers, we make UI decisions every day while writing code, and this can happen without us fully realizing it.</p><p>The day-to-day work of a developer involves making important decisions to build great applications. In this article, we&rsquo;ll focus a bit on the UI side. While we usually have design teams that decide what the app&rsquo;s colors will be, where and how buttons will be placed, developers also have the responsibility of making the right technical decisions so that the required design is implemented following best practices.</p><p>The best practics span from making decisions like which screen layout to use, whether to use an icon or an image, how to display certain information on screen, to complying with accessibility rules. UI decisions are not made only for aesthetics; they are made based on the reason behind each element we use, since they can directly impact performance and the overall experience, not just the visual aspect.</p><p>Even going a bit further, it&rsquo;s also valid for developers to add design suggestions that design teams might not think about, such as using a Lottie instead of a heavier file (besides impacting visuals, it also impacts performance), supporting dark mode, among others.</p><p>In this article, I&rsquo;ll share five design-impacting recommendations for .NET MAUI development that can help your users love using your apps.</p><h2 id="avoid-nested-layouts-as-much-as-possible">1. Avoid Nested Layouts As Much As Possible</h2><p>It&rsquo;s important to understand the potential of each layout before you start building a UI. This is because, in most cases, you can achieve exactly the same visual result using different types of layouts.</p><p>For example, the same design can be built using combinations of <code>HorizontalStackLayout</code> and <code>VerticalStackLayout</code> as by using a single grid. Visually the result may be the same, but the impact on performance is probably quite different.</p><p>Each additional layout involves more measurement and layout calculations on screen, and that, accumulated over time, ends up impacting the overall fluidity of the application.</p><p>To make this easier to understand, let&rsquo;s look at it this way: if you need to go to a place that is 10 km away, you have three options:</p><ul><li>Go by private vehicle</li><li>Go by public transportation</li><li>Go on foot</li></ul><p>All three options will allow you to reach the same destination, but not in the same way. If you walk, it will take much longer and you will arrive tired. If you use public transportation, you will spend extra time waiting and moving between stops. While if you go by private vehicle, you will arrive faster and more efficiently.</p><p>The same thing happens with layouts in an application. You can achieve the same visual result using different layout combinations, but not all of them are equally efficient. Using nested unnecessarily layouts generates more layout calculations, directly affecting performance.</p><p>One recommendation I always give is to review Grid. This layout allows you to create complex designs using a single layout, reducing the number of layouts and, therefore, the processing load.</p><p>There are also scenarios where StackLayout is completely valid. In those cases, make sure to use the one that matches your orientation&mdash;<strong>VerticalStackLayout</strong> or <strong>HorizontalStackLayout</strong>&mdash;and avoid nesting them without a clear reason.</p><p>For example, if we want to achieve a three-column, three-row layout, an example of doing it with StackLayout would be as follows:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;VerticalStackLayout Padding="16" Spacing="8"&gt; 
    &lt;HorizontalStackLayout Spacing="8"&gt; 
    &lt;BoxView Color="Red" HeightRequest="40" WidthRequest="40" /&gt; 
    &lt;BoxView Color="Green" HeightRequest="40" WidthRequest="40" /&gt; 
    &lt;BoxView Color="Blue" HeightRequest="40" WidthRequest="40" /&gt; 
    &lt;/HorizontalStackLayout&gt;
     
    &lt;HorizontalStackLayout Spacing="8"&gt; 
    &lt;BoxView Color="Orange" HeightRequest="40" WidthRequest="40" /&gt; 
    &lt;BoxView Color="Purple" HeightRequest="40" WidthRequest="40" /&gt; 
    &lt;BoxView Color="Pink" HeightRequest="40" WidthRequest="40" /&gt; 
    &lt;/HorizontalStackLayout&gt;
      
    &lt;HorizontalStackLayout Spacing="8"&gt; 
    &lt;BoxView Color="Gray" HeightRequest="40" WidthRequest="40" /&gt; 
    &lt;BoxView Color="Brown" HeightRequest="40" WidthRequest="40" /&gt; 
    &lt;BoxView Color="Black" HeightRequest="40" WidthRequest="40" /&gt; 
    &lt;/HorizontalStackLayout&gt; 
&lt;/VerticalStackLayout&gt;
</code></pre><p>But if we use a Grid, it would look like this:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid 
    RowDefinitions="Auto,Auto,Auto" 
    ColumnDefinitions="*,*,*" 
    Padding="16" 
    RowSpacing="8" 
    ColumnSpacing="8"&gt;
 
    &lt;!-- Row 1 --&gt; 
    &lt;BoxView Grid.Row="0" Grid.Column="0" Color="Red" HeightRequest="40" /&gt; 
    &lt;BoxView Grid.Row="0" Grid.Column="1" Color="Green" HeightRequest="40" /&gt; 
    &lt;BoxView Grid.Row="0" Grid.Column="2" Color="Blue" HeightRequest="40" /&gt;
    
    &lt;!-- Row 2 --&gt; 
    &lt;BoxView Grid.Row="1" Grid.Column="0" Color="Orange" HeightRequest="40" /&gt; 
    &lt;BoxView Grid.Row="1" Grid.Column="1" Color="Purple" HeightRequest="40" /&gt; 
    &lt;BoxView Grid.Row="1" Grid.Column="2" Color="Pink" HeightRequest="40" /&gt;
    
    &lt;!-- Row 3 --&gt; 
    &lt;BoxView Grid.Row="2" Grid.Column="0" Color="Gray" HeightRequest="40" /&gt; 
    &lt;BoxView Grid.Row="2" Grid.Column="1" Color="Brown" HeightRequest="40" /&gt; 
    &lt;BoxView Grid.Row="2" Grid.Column="2" Color="Black" HeightRequest="40" /&gt;

&lt;/Grid&gt;
</code></pre><aside><hr /><div class="row"><div class="col-4 u-normal-full u-small-mb0"><h4 class="u-fs20 u-fw5 u-lh125 u-mb0">Ready to explore a more powerful grid?</h4></div><div class="col-8"><p class="u-fs16 u-mb0">Check out the Progress Telerik UI for <a target="_blank" href="https://www.telerik.com/maui-ui/datagrid">.NET MAUI DataGrid</a>, a premium prebuilt grid with tons of customization options. The whole library is available to try free for 30 days.</p></div></div><hr class="u-mb3" /></aside><h2 id="add-accessibility-to-your-apps">2. Add Accessibility to Your Apps</h2><p>Sometimes we forget about what we don&rsquo;t notice, but just because we don&rsquo;t notice it doesn&rsquo;t mean it isn&rsquo;t important. Accessibility in apps allows us to adapt our applications for people with various impairments.</p><p>One quick win is to use <strong>SemanticProperties</strong>, which basically allow you to define text to be spoken out loud when a screen reader is employed. This way, if a person visually can&rsquo;t read the text, they can listen to it and stay aware of what is happening in the app.</p><p>You can add SemanticProperties to all the visual elements you&rsquo;re working with, as I show in the following example.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Entry x:Name="lastName" SemanticProperties.Description="Last name"/&gt;
</code></pre><p>For more information, I recommend reading the article &ldquo;<a target="_blank" href="https://www.telerik.com/blogs/creating-accessible-apps-semantic-properties-dotnet-maui">Creating Accessible Apps with Semantic Properties in .NET MAUI</a>.&rdquo;</p><h2 id="use-native-gradients-instead-of-gradient-images">3. Use Native Gradients Instead of Gradient Images</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-02/gradients-sample.png?sfvrsn=833b330_2" title="Gradients sample" alt="Gradients sample" /><br /><span style="font-size:11px;">Images obtained from the <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/maui/user-interface/brushes/lineargradient">official documentation</a>.</span></p><p>I&rsquo;ve noticed that many times images are added just to simulate gradients. However, with .NET MAUI we can create our own gradients using <strong>Brushes</strong>, which allows us to avoid adding unnecessary resources that can be heavier than a definition in C# or XAML.</p><p>Using native gradients allows us to play more with colors and achieve the desired design, but they also offer great benefits such as:</p><ul><li>Reducing the size of the application by avoiding additional images</li><li>Getting a more flexible UI</li><li>Gradients adapt better to different screen sizes; whereas images can look different on some devices, which forces us to maintain multiple versions of the same image</li><li>More flexibility when handling dark mode or light mode</li></ul><p>Additionally, <strong>Brushes</strong> in .NET MAUI allow us to define linear, radial or solid gradients in a simple way, reuse them through resources and maintain greater visual consistency across the application, all with a lower performance impact compared to images.</p><p>Example in code:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Border HeightRequest="120"&gt; 
    &lt;Border.Background&gt; 
    &lt;LinearGradientBrush StartPoint="0,0" EndPoint="1,1"&gt; 
    &lt;GradientStop Color="#4FACFE" Offset="0.0" /&gt; 
    &lt;GradientStop Color="#00F2FE" Offset="1.0" /&gt; 
    &lt;/LinearGradientBrush&gt; 
    &lt;/Border.Background&gt; 
&lt;/Border&gt;
</code></pre><p>To dive deeper into this topic, I recommend reading the article &ldquo;<a target="_blank" href="https://www.telerik.com/blogs/getting-started-brushes-dotnet-maui">Getting Started With Brushes in .NET MAUI</a>.&rdquo;</p><h2 id="use-preferences-correctly">4. Use Preferences Correctly</h2><p>Basically, Preferences are used to store simple information on the device, allowing faster access. A very common example of using Preferences is when we select the &ldquo;remember my email&rdquo; option when logging into an app.</p><p>What happens is that, in some cases, Preferences may be used incorrectly. Let&rsquo;s look at some common scenarios:</p><ul><li><p><strong>Storing information that should be in the database.</strong><br />My advice is to only store simple information in Preferences&mdash;data that you need at the moment and that helps you save time by avoiding unnecessary calls to an API or the database.</p></li><li><p><strong>Storing sensitive information without protection.</strong><br />In some cases, we need to store data that could be sensitive; if this is your case, always remember to <strong>encrypt</strong> the information. This way, if someone manages to access the Preferences, they won&rsquo;t be able to read the user&rsquo;s data in plain text.</p></li></ul><p>⚠️ Keep in mind that you should only store this type of information if it is <strong>absolutely necessary</strong>. Otherwise, it&rsquo;s better not to do so.</p><p>Using Preferences is very simple. You just need the following:</p><p>A <strong>Set</strong> to store the information:</p><pre class=" language-csharp"><code class="prism  language-csharp">Preferences.Default.Set("user_name", "Leo");
</code></pre><p>A <strong>Get</strong> to retrieve it:</p><pre class=" language-csharp"><code class="prism  language-csharp">string userName = Preferences.Default.Get("user_name", "Unknown");
</code></pre><p>To dive deeper into this topic, I recommend reading the article &ldquo;<a target="_blank" href="https://www.telerik.com/blogs/exploring-preferences-net-maui">Exploring Preferences in .NET MAUI</a>.&rdquo;</p><h2 id="use-fontimagesource-instead-of-icons">5. Use FontImageSource Instead of Icons</h2><p>Devs are always thinking about better performance, so here&rsquo;s a tip. Instead of using .png icons, consider using icon fonts through FontImageSource. This allows you to continue displaying icons in your UI while keeping your app lighter, since these icons behave like text rather than images.</p><p>This brings many benefits to your application, including:</p><ul><li>Font-based icons are much easier to customize. You can change their color, size and adapt them to light or dark mode without the need to create multiple versions of the same icon.</li><li>It allows you to have fewer resources in the app, reducing its size and making UI maintenance easier.</li></ul><p>To use FontImageSource, you only need the icon code you want to work with, and you can implement it as follows:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;ImageButton&gt; 
    &lt;ImageButton.Source&gt; 
    &lt;FontImageSource 
    FontFamily="MaterialIcons" 
    Glyph="&amp;#xE87C;" 
    Color="Black" 
    Size="24" /&gt; 
    &lt;/ImageButton.Source&gt; 
&lt;/ImageButton&gt;
</code></pre><p>The Glyph represents the icon that will be rendered. There are several portals where you can explore icons; as an example, you can use FontAwesome.</p><p>For example, you can go to <a target="_blank" href="https://fontawesome.com/search">https://fontawesome.com/search</a>, select an icon and in the top-right corner you&rsquo;ll see the Unicode that you can copy and paste directly into your project.
</p><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, we explored how UI decisions in .NET MAUI can make a big difference in performance and maintainability. Here are some key takeaways:</p><ul><li>From choosing the right layout and avoiding unnecessary nesting, to using gradients, icon fonts, accessibility features and storing data correctly, each decision adds up.</li><li>Building a good UI is not only about how it looks, but also about how it&rsquo;s implemented. Clean, thoughtful choices help your app feel faster, lighter and more polished&mdash;without adding unnecessary complexity.</li><li>Remember: users may not notice these decisions, but they definitely feel them. </li></ul><p>See you in the next article! &zwj;♀️✨</p>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:84b9377c-41cc-4bdd-a54e-463dad1ec10d</id>
    <title type="text">.NET 10: Secondary Toolbar Items for iOS and macOS in .NET MAUI</title>
    <summary type="text">As of .NET 10, iOS and macOS support secondary toolbar items, which are found in overflow menus and make a .NET MAUI app feel more native to the Apple user experience.</summary>
    <published>2026-03-02T18:21:06Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/net-10-secondary-toolbar-items-ios-macos-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">As of .NET 10, iOS and macOS support secondary toolbar items, which are found in overflow menus and make a .NET MAUI app feel more native to the Apple user experience.</span></p><p>When we talk about technology, we think of a world of constant changes that each day focuses on improving the previous one. In the case of .NET MAUI, this is no exception; in .NET 10, many very interesting improvements were released to make our work as devs increasingly more efficient.</p><p>This is the case with secondary toolbar Items, an improvement focused directly on the user experience. Previously, their behavior was not consistent across all platforms, especially on iOS and macOS. Now, we have support that allows secondary actions to behave in a more natural way and align with the Apple conventions, making our applications feel much more native.</p><h2 id="what-are-secondary-toolbar-items">What Are Secondary Toolbar Items?</h2><p>These are options that live in the toolbar. Instead of being displayed directly in the toolbar, they are grouped inside a secondary menu that is shown when selecting their primary action.</p><p>For example: Location &rarr; North America.</p><p>This way, only the most important actions remain visible in the main toolbar, which helps reduce visual clutter and improves the user experience.</p><p><strong>From .NET 10 onward, the official documentation states:</strong></p><p>&ldquo;iOS and macOS now support secondary toolbar items, providing better alignment with platform conventions.&rdquo; </p><p>This improvement is not just a visual change; it introduces several important enhancements for iOS and macOS that directly impact how secondary toolbar items behave and integrate with the platform, making them feel much more native, such as:</p><h2 id="automatic-detection">Automatic Detection</h2><pre class=" language-xml"><code class="prism  language-xml">&lt;ToolbarItem Text="Copy" Order="Secondary" /&gt;
&lt;ToolbarItem Text="Paste" Order="Secondary"/&gt;
</code></pre><p>When configuring <strong>ToolbarItems</strong>, we need to define whether they will be primary or secondary. With this improvement, all items marked in the <code>Order</code> property with the value <code>Secondary</code> are automatically grouped into the secondary menu, which means we don&rsquo;t need to add any extra configuration or write additional code for it to work.</p><p>This is especially valuable when we want to maintain a native experience in our applications.</p><h2 id="modern-ios-pattern">Modern iOS Pattern</h2><pre class=" language-xml"><code class="prism  language-xml">&lt;ToolbarItem Text="Share" Order="Secondary" /&gt;
</code></pre><p>.NET MAUI now uses iOS 13+ APIs, which means it displays a modern menu design to present secondary options. This design follows the established rules and respects the <strong>Human Interface Guidelines</strong>.</p><p>The <strong>Human Interface Guidelines (HIG)</strong> are a set of design recommendations created by Apple, which align a unique and consistent experience across its platforms, indicating how applications should look and behave.</p><p><strong>You can define the order of your items!</strong> </p><pre class=" language-xml"><code class="prism  language-xml">&lt;ToolbarItem Text="Go to document" Order="Secondary" Priority="0" /&gt;
</code></pre><p>Keeping a logical order in your items is also important. When adding a ToolbarItem, there is a property called <code>Priority</code>, which is responsible for defining the order in which the options will be displayed in the menu, both primary and secondary.</p><p>Items are ordered numerically, from lowest to highest, starting at 0. This allows us to decide which actions should appear first, helping maintain a clear hierarchy of what we want to present to the user.</p><h2 id="how-is-the-positioning-handled">How Is the Positioning Handled?</h2><p>The secondary menu is displayed by default on the <strong>right</strong> side of the toolbar. It also has the ability to automatically adapt when <strong>Right-To-Left (RTL)</strong> is enabled in your app.</p><p>In case you didn&rsquo;t know, <strong>RTL</strong> refers to the reading and writing direction of certain languages. This means your .NET MAUI app respects the conventions of each language, providing a more accessible and adaptable user experience. This behavior applies to all visual elements, including the secondary menu.</p><h2 id="customizable-icon">Customizable Icon</h2><p>By default, secondary toolbar items are grouped into a pull-down menu that uses the system <strong>ellipsis (⋯)</strong> icon (<code>UIImage.GetSystemImage("ellipsis.circle")</code>). This icon, defined by <strong>Apple</strong> in its <strong>Human Interface Guidelines</strong>, is used to represent additional, secondary or less frequent actions, so that the menu looks and behaves like any other native menu on iOS and macOS.</p><p>Although this icon is recommended, it is not mandatory. If your app requires a different visual representation, .NET MAUI allows you to customize the icon, enabling the secondary menu to better align with your app&rsquo;s visual requirements while preserving its native behavior.</p><p>⚠️ My recommendation is that whenever this icon needs to be changed, it&rsquo;s important for the design team to be aligned and aware that a rule defined by Apple is being modified. There&rsquo;s nothing wrong with changing it, but it&rsquo;s essential to have a clear <strong>WHY</strong> behind the decision.</p><p>Another important detail to highlight is that this menu is <strong>dynamic</strong>. If the menu is open and any of an item&rsquo;s properties change at runtime&mdash;such as its text, enabled state or visibility&mdash;the system automatically rebuilds and closes the menu to reflect those updates.</p><p>This allows users to always see up-to-date and consistent information, preventing invalid actions and maintaining a reliable, native user experience.</p><h2 id="in-summary">In Summary</h2><ul><li><strong>Primary toolbar items</strong> are displayed directly in the toolbar.</li><li><strong>Secondary toolbar items</strong> are grouped inside the overflow (secondary) menu.</li></ul><p> The official documentation recommends <strong>keeping label text short</strong> so it fits in the dropdown menu, thus reducing the risk of cross-platform inconsistencies.</p><p>A basic XAML implementation about a ToolbarItems implementation, would look like the following example:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;ContentPage.ToolbarItems&gt;
    &lt;!-- Primary toolbar items --&gt;
    &lt;ToolbarItem Text="Save" Order="Primary" Priority="0" /&gt;
    &lt;ToolbarItem Text="Edit" Order="Primary" Priority="1" /&gt;
    
    &lt;!-- Secondary toolbar items --&gt;
    &lt;ToolbarItem Text="Share" Order="Secondary" Priority="0" /&gt;
    &lt;ToolbarItem Text="Delete" Order="Secondary" Priority="1" /&gt;
    &lt;ToolbarItem Text="Settings" Order="Secondary" Priority="2" /&gt;
&lt;/ContentPage.ToolbarItems&gt;
</code></pre><p><span style="font-size:11px;">Example obtained from official documentation.</span></p><p>And that&rsquo;s it!  With .NET 10, <strong>secondary toolbar items</strong> in .NET MAUI take an important step forward, especially on iOS and macOS. These improvements bring a more native, consistent and predictable behavior by aligning toolbar actions with platform conventions, that is why it&rsquo;s important to keep you up to date with the news!</p><p>If you have any questions or would like me to dive deeper into related topics, feel free to leave a comment&mdash;I&rsquo;ll be happy to help! </p><p>See you in the next article! &zwj;♀️✨</p><h3 id="references">References</h3><p>The explanation was based on the official documentation:</p><ul><li><a href="https://learn.microsoft.com/en-us/dotnet/maui/whats-new/dotnet-10?view=net-maui-10.0">https://learn.microsoft.com/en-us/dotnet/maui/whats-new/dotnet-10?view=net-maui-10.0</a></li></ul><aside><hr data-sf-ec-immutable="" /><div class="row"><div class="col-4 u-normal-full u-small-mb0"><h4 class="u-fs20 u-fw5 u-lh125 u-mb0">.NET 10 on iOS: Updates and Notes for .NET MAUI Developers</h4></div><div class="col-8"><p class="u-fs16 u-mb0">Here&rsquo;s what else you may have missed in <a target="_blank" href="https://www.telerik.com/blogs/net-10-ios-updates-notes-net-maui-developers">.NET 10 for .NET MAUI</a> if you&rsquo;re a developer targeting iOS.</p></div></div></aside>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:74e39893-76ea-4619-9839-60136b04bf11</id>
    <title type="text">Simplifying Grid Layout in .NET MAUI Using Extension Methods</title>
    <summary type="text">The grid extension methods from the Community Toolkit can make working with grids in .NET MAUI cleaner. Learn more!</summary>
    <published>2026-02-23T21:13:59Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/simplifying-grid-layout-net-maui-using-extension-methods"/>
    <content type="text"><![CDATA[<p><span class="featured">The grid extension methods from the Community Toolkit can make working with grids in .NET MAUI cleaner. Learn more!</span></p><p>The grid is one of the layouts that provides the best performance for your .NET MAUI apps, and I love it because it&rsquo;s also very flexible. You can create designs that look complex, and a grid even works as a replacement for the old <strong>RelativeLayout</strong>.</p><p>But beyond all its advantages, today we&rsquo;ll talk about some <strong>tips and tricks</strong> to help you get the most out of it using the <strong>extension methods</strong> that the Maui.Community.Toolkit provides for the grid.</p><h2 id="what-is-an-extension-method-">What Is an Extension Method? </h2><p>An extension method is a C# feature that allows you to add methods to an existing type, such as classes, interfaces or structs. Thanks to them, you don&rsquo;t need to inherit from a class or modify its original code to use new functionality. It&rsquo;s like giving superpowers to a class that already exists.</p><p>For example, if the grid originally didn&rsquo;t have a method called <code>Rows()</code>, you could create an extension method to add it, and it would behave as if that method were part of the grid itself.</p><h2 id="what-are-grid-extension-methods">What Are Grid Extension Methods?</h2><p>Grid extensions are a set of extensions specifically designed for the grid included in the Maui.Community.Toolkit. Let&rsquo;s explore which extensions are available and what each of them does!</p><h3 id="row">Row</h3><p>Its purpose is to set the <code>Grid.Row</code> value and, optionally, the <code>RowSpan</code> (<code>Grid.RowSpan</code>) if you want an element to extend horizontally across multiple rows.</p><p>This method can be used with any element that inherits from BindableObject, such as Label, Button, Image, etc.</p><p>Here&rsquo;s an example of how to implement it:</p><h4 id="❌-without-extension-methods">❌ Without Extension Methods</h4><pre class=" language-csharp"><code class="prism  language-csharp">var button = new Button { Text = "This Button is in Row 1 and spans 5 rows" }; 
    Grid.SetRow(button, 1); 
    Grid.SetRowSpan(button, 5); 
var grid = new Grid { Children = { button } };
</code></pre><h4 id="✅-using-extension-methods">✅ Using Extension Methods</h4><pre class=" language-csharp"><code class="prism  language-csharp">new Grid { Children = { new Button().Text("This Button is in Row 1 and spans 5 rows").Row(1, 5) } };
</code></pre><h3 id="column">Column</h3><p>Its purpose is to set the <code>Grid.Column</code> value and, optionally, the <code>ColumnSpan</code> (<code>Grid.ColumnSpan</code>) if you want an element to extend vertically across multiple columns. This method can be used with any element that inherits from BindableObject.</p><p>Here&rsquo;s an example of how to implement it:</p><h4 id="❌-without-extension-methods-1">❌ Without Extension Methods</h4><pre class=" language-csharp"><code class="prism  language-csharp">var button = new Button { Text = "This Button is in Column 2 and spans 4 columns" }; 
    Grid.SetColumn(button, 2); 
    Grid.SetColumnSpan(button, 4); 
var grid = new Grid { Children = { button } };
</code></pre><h4 id="✅-using-extension-methods-1">✅ Using Extension Methods</h4><pre class=" language-csharp"><code class="prism  language-csharp">new Grid { Children = { new Button().Text("This Button is in Column 2 and spans 4 columns").Column(2, 4) } };
</code></pre><h3 id="defining-rows--columns">Defining Rows &amp; Columns</h3><p>The Toolkit provides an extension that lets you define your Grid&rsquo;s rows and columns in a simpler and more direct way, offering <strong>shorter, more expressive equivalents for common GridLength values</strong>. This is possible thanks to the following helpers:</p><ul><li><code>Columns.Define</code></li><li><code>Rows.Define</code></li></ul><p>To use them, you just need to add the following line at the top of your class:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span> <span class="token keyword">static</span> CommunityToolkit<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Markup<span class="token punctuation">.</span>GridRowsColumns<span class="token punctuation">;</span>
</code></pre><p>This <strong><code>using static</code></strong> allows you to replace long expressions like <strong><code>GridLength.Auto</code></strong> or new <strong><code>GridLength(2, GridLength.Star)</code></strong> with their shorter forms such as Auto, Star, Stars(2), etc.</p><p>For better clarity, here&rsquo;s a comparison table:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-02/01_comparison.png?sfvrsn=650444e1_2" alt="Comparison table: What you would normally write: GridLength.Auto - With Grid extensions: Auto - Meaning: Adjusts to the content size - What you would normally write: new GridLength(1, GridLength.Star) - With Grid extensions: Star - Meaning: Takes available space (1*) - What you would normally write: new GridLength(2, GridLength.Star) - With Grid extensions: Stars(2) - Meaning: Takes 2× the available space (2*) - What you would normally write: new GridLength(20, GridLength.Absolute) - With Grid extensions: 20 - Meaning: Absolute size of 20**" /></p><p>And here&rsquo;s how that translates into code:</p><h4 id="❌-without-extension-methods-2">❌ Without Extension Methods</h4><pre class=" language-csharp"><code class="prism  language-csharp">ColumnDefinitions = new ColumnDefinitionCollection 
{ 
    new ColumnDefinition { Width = new GridLength(20, GridLength.Absolute) }, 
    new ColumnDefinition { Width = new GridLength(1, GridLength.Star) }, 
    new ColumnDefinition { Width = new GridLength(2, GridLength.Star) } 
};
</code></pre><h4 id="✅-using-extension-methods-2">✅ Using Extension Methods</h4><pre class=" language-csharp"><code class="prism  language-csharp">ColumnDefinitions = Columns.Define(20, Star, Stars(2));
</code></pre><p> When you compare both versions, look at everything you gain:</p><ul><li>Far less code&mdash;from six lines down to <strong>just one</strong></li><li>Much more readable and expressive</li><li>And the best part: <strong>way easier to maintain</strong></li></ul><h3 id="defining-rows--columns-using-enums">Defining Rows &amp; Columns Using Enums</h3><p>This is my favorite one!  Normally, when defining the rows and columns of a grid, you use numeric values: row 2, column 2, etc. But the more rows and columns you have, the harder it becomes to identify, read and maintain that layout.</p><p>Now imagine that instead of numbers, you could use names. Well, now you can! </p><p>The Community Toolkit allows you to name your rows and columns using enums (for example: <code>Row.Username</code>, <code>Column.UserInput</code>). This makes your code so much more readable, easier to understand and incredibly simple when identifying or modifying any coordinate inside the Grid.</p><p>And now, let&rsquo;s see how to do it!</p><h4 id="step-1-import-the-required-helpers">Step 1: Import the Required Helpers</h4><pre class=" language-csharp"><code class="prism  language-csharp">using static CommunityToolkit.Maui.Markup.GridRowsColumns;
</code></pre><h4 id="step-2-create-your-enum-for-both-rows-and-columns">Step 2: Create Your Enum for Both Rows and Columns</h4><p>First, the rows:</p><pre class=" language-csharp"><code class="prism  language-csharp">enum Row { Username, Password, Submit }
</code></pre><p>Then the columns:</p><pre class=" language-csharp"><code class="prism  language-csharp">enum enum Column { Description, UserInput }
</code></pre><h4 id="step-3-use-the-enum">Step 3: Use the Enum</h4><p>Now that we&rsquo;ve created our enums, let&rsquo;s define the grid&rsquo;s rows and columns using them, just like in the following example:</p><pre class=" language-csharp"><code class="prism  language-csharp">RowDefinitions = Rows.Define( 
(Row.Username, 30), 
(Row.Password, 30), 
(Row.Submit, Star)), 

ColumnDefinitions = Columns.Define( 
(Column.Description, Star), 
(Column.UserInput, Star)),
</code></pre><p>You can also use the enum to position your controls.</p><p>Instead of doing something like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">.Row(0).Column(1)
</code></pre><p>You can simply do:</p><pre class=" language-csharp"><code class="prism  language-csharp">.Row(Row.Username).Column(Column.Description)
</code></pre><p>That&rsquo;s it!!  Much cleaner, more expressive and easier to understand at a glance.</p><h3 id="rowspan--columnspan">RowSpan &amp; ColumnSpan</h3><p><code>RowSpan</code> and <code>ColumnSpan</code> are extension methods that allow you to define the number of rows or columns, respectively, that the grid should occupy. For example, if my grid has three rows and two columns, you would have something like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">new Button() 
  .Text("Button to test")  
  .RowSpan(3) 
  .ColumnSpan(2)
</code></pre><p>And you can get even more out of your enum by using these special helpers:</p><p>➖ <code>All&lt;TEnum&gt;()</code> &ndash; This indicates that the control should occupy all the rows and/or columns defined in your enum, respectively. For example, if I have the following enums:</p><pre class=" language-csharp"><code class="prism  language-csharp">enum Row { Username, Password, Submit }
enum Column { Description, UserInput }
</code></pre><p>My definition would look like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">new Button() 
   .Text("Button to test") 
   .RowSpan(All&lt;Row&gt;()) 
   .ColumnSpan(All&lt;Column&gt;())
</code></pre><p>➖ <code>Last&lt;TEnum&gt;</code> &ndash; Allows you to place a control in the last row or last column defined in your enum. You can do it as follows:</p><p>⚠️ For this example, we&rsquo;ll use the enums defined above (Rows and Columns). In the code, a button is added to the last row and last column of the grid.</p><pre class=" language-csharp"><code class="prism  language-csharp">new Button() 
   .Text("Button to test") 
   .Row(Last&lt;Row&gt;()) 
   .Column(Last&lt;Column&gt;());
</code></pre><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, you explored how the grid extension methods from the <strong>CommunityToolkit.Maui.Markup</strong> make working with grids in .NET MAUI simpler, cleaner and much more expressive. You learned what each helper does, how to define rows and columns with a shorter syntax, and how the Row/Column extension methods improve readability and reduce boilerplate.</p><p>Now you have the tools to make grid extensions your ally&mdash;helping you build layouts faster, write more maintainable UI code and create interfaces that are both easier to understand and easier to evolve over time.</p><p>If you have any questions or want me to cover more related topics, feel free to leave a comment. I&rsquo;d be happy to help you!  See you in the next article! &zwj;♀️✨</p><h3 id="references">References</h3><p>The explanation was based on the official documentation:</p><ul><li><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/markup/extensions/grid-extensions">https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/markup/extensions/grid-extensions</a></li></ul><hr /><h3 id="need-a-more-robust-grid">Need a More Robust Grid?</h3><p>The Progress Telerik UI for <a target="_blank" href="https://www.telerik.com/maui-ui/datagrid">.NET MAUI DataGrid</a> is one of the most powerful native MAUI grids available. It comes with 70+ other components in a free 30-day trial if you want to explore it in detail.</p><p><a target="_blank" href="https://www.telerik.com/try/ui-for-maui" class="Btn">Try Telerik UI for .NET MAUI</a></p>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:f02f5e8b-9832-4ad7-8082-c2f72ce4b29b</id>
    <title type="text">Next Productivity Leap: Telerik and Kendo UI 2026 Q1 Release Is Here</title>
    <summary type="text">With new agentic tools for document processing, RAG-powered workflows, improved accessibility in MCP tools and a new set of AI‑ready UI components, the 2026 Q1 release lets you bring intelligence directly into your applications using the same .NET and JavaScript components you already rely on.</summary>
    <published>2026-02-18T17:25:28Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Iva Borisova </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/next-productivity-leap-telerik-kendo-ui-2026-q1-release"/>
    <content type="text"><![CDATA[<p><span class="featured">With new agentic tools for document processing, RAG-powered workflows, improved accessibility in MCP tools and a new set of AI‑ready UI components, the 2026 Q1 release lets you bring intelligence directly into your applications using the same .NET and JavaScript components you already rely on.</span></p><p>The Progress Telerik and Kendo UI 2026 Q1 release continues to bring AI directly into everyday application workflows, moving it more and more into practical, real-world scenarios, including improved accessibility in AI‑generated UIs.</p><p>At the same time, this first release of 2026 strengthens the core foundations you rely on, with latest framework support and integrations, enhanced UI customization tools and a growing set of new and improved components that make it easier to design, build and evolve complex applications.</p><p>Let the release speak for itself! Here&rsquo;s a closer look at the key highlights shaping the Telerik and Kendo UI 2026 Q1 release.</p><h2 id="ai-powered-development-and-document-workflows">AI-Powered Development and Document Workflows</h2><h3 id="preview-agentic-tools-for-telerik-document-processing-libraries">[Preview] Agentic Tools for Telerik Document Processing Libraries (DPL)</h3><p>Build intelligent document processing workflows with ease. The <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/ai-tools/agent-tools/overview">DPL Agentic Tools</a> let users extract structured data, edit content, convert formats, generate new Excel or PDF files and perform analysis on Excel documents directly inside .NET apps with no separate services required.</p><p>DPL Agentic Tools are available with a <a target="_blank" href="https://www.telerik.com/purchase.aspx?filter=web#subscription">Telerik or Kendo UI subscription</a>.</p><h3>New Agentic RAG .NET SDK</h3><p>New Agentic RAG .NET SDK: .NET developers now have a straightforward way to integrate retrieval‑augmented generation workflows into their applications. Powered by our own <a target="_blank" href="https://www.progress.com/agentic-rag">Progress Agentic RAG</a>, the SDK provides a stable foundation for creating context‑aware AI solutions. Available as a <a target="_blank" href="https://www.nuget.org/packages/Progress.Nuclia/1.0.0-preview1">public NuGet package</a> with sample integrations for <a target="_blank" href="https://github.com/telerik/telerik-blazor-progress-rag-demo">Blazor</a>, and <a target="_blank" href="https://github.com/telerik/telerik-maui-progress-rag-demo">.NET MAUI</a>, the SDK makes it easy to ingest data, run semantic search, and build AI‑powered app experiences using familiar .NET patterns.</p><h3 id="improved-accessibility-in-telerik-agentic-ui-generator">Improved Accessibility in Telerik Agentic UI Generator</h3><p>The <a target="_blank" href="https://www.telerik.com/mcp-servers">Agentic UI Generator</a> now emphasizes the Telerik and Kendo UI component‑specific accessibility implementation details. It helps you apply these patterns consistently across your UI and surfaces relevant accessibility API references for the specific components you&rsquo;re using.</p><p>The Agentic UI Generator is available with a Telerik or Kendo UI subscription.</p><h3 id="ai-coding-assistants-improvements">AI Coding Assistants Improvements</h3><p>The Telerik UI for Blazor validator tool is now available to help reduce hallucinations and improve overall code reliability. A new icons generation tool for existing and custom icons is also introduced with this release. The Telerik UI for ASP.NET Core/MVC and Blazor assistants are transitioned to native .NET NuGet distributions, making installation and adoption simpler and more enterprise friendly.</p><p>AI Coding Assistants are available with a Telerik or Kendo UI subscription.</p><h2 id="ai-interface-and-smart-components">AI Interface and Smart Components</h2><h3 id="new-ai-smart-paste-component">New AI Smart Paste Component</h3><p>Reduce manual typing and speed up data entry in your apps. The AI Smart Paste automatically converts unstructured text into structured inputs by mapping content from emails, documents or messages to the right fields with zero extra effort.</p><p>Learn more:</p><ul><li><a target="_blank" href="https://www.telerik.com/kendo-angular-ui/components/buttons/smartpastebutton">Kendo UI for Angular AI Smart Paste</a></li><li><a target="_blank" href="https://www.telerik.com/kendo-react-ui/components/buttons/smartpaste">KendoReact AI Smart Paste</a></li><li><a target="_blank" href="https://demos.telerik.com/kendo-ui/smartpastebutton/index">Kendo UI for jQuery AI Smart Paste</a></li><li><a target="_blank" href="https://demos.telerik.com/blazor-ui/smartpastebutton/overview">Telerik UI for Blazor AI Smart Paste</a></li><li><a target="_blank" href="https://demos.telerik.com/aspnet-core/smartpastebutton">Telerik UI for ASP.NET Core AI Smart Paste</a></li><li><a target="_blank" href="https://demos.telerik.com/aspnet-mvc/smartpastebutton">Telerik UI for ASP.NET MVC AI Smart Paste</a></li><li><a target="_blank" href="https://demos.telerik.com/aspnet-ajax/smartpastebutton/overview/defaultcs.aspx">Telerik UI for ASP.NET AJAX AI Smart Paste</a></li></ul><h3 id="new-promptbox-component">New PromptBox Component</h3><p>Designed for seamless interaction with AI‑powered workflows, the PromptBox component provides a dedicated space where users can craft prompts, send messages and engage naturally with AI language models.</p><p>Learn more: </p><ul><li><a target="_blank" href="https://www.telerik.com/kendo-angular-ui/components/conversational-ui/promptbox">Kendo UI for Angular PromptBox</a></li><li><a target="_blank" href="https://www.telerik.com/kendo-react-ui/components/conversationalui/promptbox">KendoReact PromptBox</a></li><li><a target="_blank" href="https://demos.telerik.com/kendo-ui/promptbox/index">Kendo UI for jQuery PromptBox</a></li><li><a target="_blank" href="https://demos.telerik.com/blazor-ui/promptbox/overview">Telerik UI for Blazor PromptBox</a></li><li><a target="_blank" href="https://demos.telerik.com/aspnet-core/promptbox">Telerik UI for ASP.NET Core PromptBox</a></li><li><a target="_blank" href="https://demos.telerik.com/aspnet-mvc/promptbox">Telerik UI for ASP.NET MVC PromptBox</a></li></ul><h3 id="smartbox--semantic-search-and-prompting-in-telerik-and-kendo-ui-datagrid">SmartBox: Semantic Search and Prompting in Telerik and Kendo UI DataGrid</h3><p>An AI-enabled DataGrid feature that combines natural-language prompting, keyword search and semantic search into a single experience, allowing users to query, filter and manipulate grid data using the interaction option that best fits their needs. Users can control the grid through prompts to apply actions such as filtering, sorting, highlighting and grouping. </p><p>Semantic Search enhances discovery by understanding intent and context, returning relevant results even when the exact search terms are not present in the data.</p><p>Learn more: </p><ul><li><a target="_blank" href="https://www.telerik.com/kendo-angular-ui/components/grid/smart-grid/ai-toolbar-tool">Kendo UI for Angular Grid SmartBox</a></li><li><a target="_blank" href="https://www.telerik.com/kendo-react-ui/components/grid/smart/basic-operations">KendoReact SmartBox</a></li><li><a target="_blank" href="https://demos.telerik.com/kendo-ui/grid/ai-smartbox">Kendo UI for jQuery Grid SmartBox</a></li><li><a target="_blank" href="https://demos.telerik.com/blazor-ui/grid/ai-smart-box">Telerik UI for Blazor Grid SmartBox</a></li><li><a target="_blank" href="https://demos.telerik.com/aspnet-core/grid/ai-smartbox">Telerik UI for ASP.NET Core Grid SmartBox</a></li><li><a target="_blank" href="https://demos.telerik.com/aspnet-mvc/grid/ai-smartbox">Telerik UI for ASP.NET MVC Grid SmartBox</a></li></ul><h3 id="smart-grid-ai-chat-integration-demo">Smart Grid: AI Chat Integration Demo</h3><p>See how integrating the Telerik and Kendo UI AI Chat with the Data Grid delivers a complete, end-to-end AI prompting experience over the grid multi-step flows and contextual interactions driven through the Chat component.</p><p>Learn more: </p><ul><li><a target="_blank" href="https://www.telerik.com/kendo-angular-ui/components/grid/smart-grid/ai-chat-assistant">Kendo UI for Angular Grid AI Chat Integration</a></li><li><a target="_blank" href="https://www.telerik.com/kendo-react-ui/components/grid/smart/ai-chat-assistant">KendoReact Grid AI Chat Integration</a></li><li><a target="_blank" href="https://demos.telerik.com/kendo-ui/grid/ai-chat-integration">Kendo UI for jQuery Grid AI Chat Integration Demo</a></li><li><a target="_blank" href="https://demos.telerik.com/blazor-ui/grid/ai-chat-assistant">Telerik UI for Blazor Grid AI Chat Integration Demo</a></li><li><a target="_blank" href="https://demos.telerik.com/aspnet-core/grid/ai-chat-integration">Telerik UI for ASP.NET Core Grid AI Chat Integration Demo</a></li><li><a target="_blank" href="https://demos.telerik.com/aspnet-mvc/grid/ai-chat-integration">Telerik UI for ASP.NET MVC Grid AI Chat Integration Demo</a> </li><li><a target="_blank" href="https://www.telerik.com/maui-ui/documentation/controls/datagrid/smart-ai-features/ai-assistant/overview">Telerik UI for .NET MAUI Grid AI Chat Integration</a></li></ul><h3 id="telerik-ui-for-blazor-microsoft.extensions.ai-chat-component-integration">Telerik UI for Blazor: Microsoft.Extensions.AI Chat Component Integration</h3><p>With native Microsoft.Extensions.AI integration, the Telerik UI for Blazor Chat now delivers an AI‑ready experience out of the box, automatically sending messages to a configured IChatClient and returning responses through the built‑in AI pipeline.</p><h2 id="richer-ui-customization">Richer UI Customization</h2><h3 id="performance-updates-in-progress-themebuilder">Performance Updates in Progress ThemeBuilder</h3><p>The UI customization tool loads and applies changes noticeably faster, so teams can preview, iterate and ship themes with less waiting and fewer interruptions.</p><h3 id="pixel‑accurate-component-previews">Pixel‑Accurate Component Previews</h3><p>Kendo UI components in ThemeBuilder now match production output, reducing styling surprises so what you design is what users see across variants and interaction states.</p><h3 id="enhanced-customization">Enhanced Customization</h3><p>Templates have been enhanced to expose more parts, states and variations, giving designers and developers finer control over visual details without custom workarounds.</p><h2 id="new-classic-components">New Classic Components</h2><h3 id="new-dropdowntree-in-telerik-ui-for-blazor">New DropDownTree in Telerik UI for Blazor</h3><p>By combining the familiar structure of a TreeView with the convenience of a dropdown, the new <a target="_blank" href="https://demos.telerik.com/blazor-ui/dropdowntree/overview">Blazor DropDownTree component</a> offers an intuitive, space‑efficient interface that makes browsing, expanding and selecting nested items effortless.</p><h3 id="new-editor-in-telerik-ui-for-.net-maui">New Editor in Telerik UI for .NET MAUI</h3><p>Gain a richer, more flexible text‑input experience designed for scenarios that go beyond a simple entry field. Offering a multiline editor with built‑in scrolling, the new <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/controls/editor/overview">MAUI Editor</a> makes it easy for users to draft longer text, edit content and work comfortably within constrained mobile and desktop layouts.</p><h3 id="new-speech-to-text-button-in-desktop-products">New Speech-to-Text Button in Desktop Products</h3><p>Already available in all Telerik and Kendo UI web and mobile libraries, the Speech-to-Text Button is now ready to empower desktop users, too. They can convert speech into text with a single click, making it easy to add voice input to forms, search bars, chat interfaces and other interactive scenarios.</p><p>Learn more:</p><ul><li><a target="_blank" href="https://www.telerik.com/products/wpf/documentation/controls/radbuttons/features/speech-to-text-button">Telerik UI for WPF Speech-to-Text Button</a></li><li><a target="_blank" href="https://www.telerik.com/products/winforms/documentation/controls/speechtotextbutton/overview">Telerik UI for WinForms Speech-to-Text Button</a></li></ul><h2 id="feature-improvements-beyond-ai">Feature Improvements Beyond AI</h2><h3 id="additional-datagrid-enhancements">Additional DataGrid Enhancements</h3><p>Alongside the new smart features, this release brings developer‑focused improvements to the traditional DataGrid experience.</p><p>Features like CSV export, stacked layout modes and column min/max width constraints in KendoReact give more control over how data is presented and consumed.</p><p>The customizable keyboard shortcuts and improved sorting performance make the Telerik UI for Blazor Grid feel faster and easier to tailor to complex scenarios. Data interaction with grouping‑sort behavior allows grouped data to be reordered directly from the UI.</p><h3 id="chat-ui-improvements-across-the-board">Chat UI Improvements Across the Board</h3><p>Users can now quickly jump to the most recent messages with a dedicated scroll-to-bottom button. Message delivery is also more transparent with improved status indicators that can display text, icons or both, along with a new failed message state that allows users to easily resend messages with a single click.</p><p>Suggestions have also been refined. Clicked items can optionally disappear from the list and can now be inserted into the input for editing before sending.</p><p>These enhancements are powered by a more capable input experience, supporting single-line, multiline and auto-expand modes, customizable prefix and suffix content, and built-in actions like speech-to-text and file selection, making the Chat control more flexible, modern and user-friendly.</p><p>All these features make the component equally well suited for AI-to-human interactions and traditional human-to-human conversations.</p><h3 id="diagram-interaction-enhancements">Diagram Interaction Enhancements</h3><p>You can now add text directly to connections with flexible positioning options, display tooltips on nodes and connections, and benefit from larger grab points that make starting new connections more precise.</p><p>Interaction is smoother with resizable connection segments, improved snapping between shapes and connectors, and automatic scrollbars when the canvas exceeds the viewport.</p><p>Additional upgrades such as keyboard navigation and resizable shapes contribute to a more polished and accessible diagramming experience.</p><h3 id="new-in-kendo-ui-for-angular-spreadsheet-scheduler-and-pdfviewer">New in Kendo UI for Angular Spreadsheet, Scheduler and PDFViewer</h3><p><strong><a target="_blank" href="https://www.telerik.com/kendo-angular-ui/components/scheduler">Angular Scheduler</a></strong> gains more flexible calendar control with options to show or hide days, weekends and other non‑working periods, along with improved slot styling.</p><p>The <strong><a target="_blank" href="https://www.telerik.com/kendo-angular-ui/components/spreadsheet">Angular Spreadsheet</a></strong> now enables Excel‑like filtering, sorting with visual indicators and comprehensive copy/paste/cut event handling.</p><p>Meanwhile, the <strong><a target="_blank" href="https://www.telerik.com/kendo-angular-ui/components/pdfviewer">Angular PDFViewer</a></strong> introduces support for form filling and blank pages and reuses the modern Toolbar component.</p><h3 id="telerik-reporting-and-report-server-updates">Telerik Reporting and Report Server Updates</h3><p>With this release, Telerik reporting tools include inline image support in HtmlTextBox, repeat‑on‑every‑page table group headers, improved .NET‑based serialization and full Unicode BiDi text handling for accurate multilingual rendering&mdash;all designed to boost performance, readability and global accessibility. Developers also gain access to the downloadable .NET reporting source code, making debugging, customization and exploration easier.</p><h3 id="core-document-processing-enhancements">Core Document Processing Enhancements</h3><p>New MIME type support for embedded files allows developers to explicitly define how attachments like XML, JSON or CSV payloads are represented inside PDFs, while automatic file‑format detection makes it easier to load documents from byte arrays. Compliance is further improved through EU DSS‑aligned digital signing, helping validate PDFs against official European Commission standards. Additionally, Timestamp Server support in PdfStreamSigner enables trusted, verifiable timestamps that support long‑term signature validity.</p><h2 id="modern-framework-support-and-integrations">Modern Framework Support and Integrations</h2><h3 id="angular-v21-adoption">Angular v21 Adoption</h3><p><a target="_blank" href="https://www.telerik.com/blogs/angular-21-my-favorite-new-features-quick-demo-look-whats-next">Kendo UI for Angular is fully aligned with Angular v21</a>, enabling seamless compatibility with the latest framework updates and giving developers immediate access to improved performance, modern APIs and long‑term platform stability.</p><h3 id="net-11-preview-1-compatibility">.NET 11 Preview 1 Compatibility</h3><p>Telerik UI libraries and tools are compatible with .NET 11 Preview 1, allowing early adopters to start experimenting with the latest .NET platform updates.</p><h3 id="jquery-4.0.0-support">jQuery 4.0.0 Support</h3><p>After almost a decade, jQuery 4.0.0 has arrived, removing legacy browser support, dropping deprecated APIs, aligning event behavior with modern standards and overall modernizing the codebase. <a target="_blank" href="https://www.telerik.com/blogs/jquery-4-support-whats-new-how-kendo-ui-has-you-covered">Kendo UI for jQuery is fully compatible and ready for jQuery 4</a>.</p><h3 id="justmock-gitlab-integration">JustMock-GitLab integration</h3><p><a target="_blank" href="https://www.telerik.com/products/justmock/documentation/integration/continuous-integration/gitlab">JustMock now integrates with GitLab CI/CD</a>, enabling teams to run and automate JustMock‑based unit tests directly within their GitLab pipelines.</p><h2 id="what’s-new--release-history">What&rsquo;s New &amp; Release History</h2><p>To see everything that is new in 2026 Q1, visit the <a target="_blank" href="https://www.telerik.com/support/whats-new">What&rsquo;s New in Telerik and Kendo UI</a> page. For a deeper dive into each product, follow the links below.</p><table><style>table,
 th,
        td {
            border: 1px;
            border-color: #bdbdba;
            border-style: dotted;
            border-collapse: collapse;
            margin-right: auto;
            text-align: left;
        }
    </style>
 <thead><tr><th style="width:33.3333%;padding:5px;"><strong>Product</strong></th><th style="width:33.3333%;padding:5px;"><strong>What&rsquo;s New</strong></th><th style="width:33.3333%;padding:5px;"><strong>Release History</strong></th></tr></thead><tbody><tr><td style="width:33.3333%;padding:5px;">Kendo UI for Angular</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/kendo-angular-ui/2026-q1">What&rsquo;s New in Kendo UI for Angular</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/kendo-angular-ui/components/changelogs/kendo-angular-ui#v23.0.1">Kendo UI for Angular Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">KendoReact</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/kendo-react-ui/2026-q1">What&rsquo;s New in KendoReact</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/kendo-react-ui/components/changelogs/ui-for-react#v14.0.0">KendoReact Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Kendo UI for Vue</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/kendo-vue-ui/2026-q1">What&rsquo;s New in Kendo UI for Vue</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/kendo-vue-ui/components/changelogs/ui-for-vue#v8.0.0">Kendo UI for Vue Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Kendo UI for jQuery</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/kendo-jquery-ui/2026-q1">What&rsquo;s New in Kendo UI for jQuery</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/kendo-ui/release-history/kendo-ui-for-jquery-2026-1-212-(2026-q1)">Kendo UI for jQuery Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik UI for Blazor</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/blazor-ui/2026-q1">What&rsquo;s New in Telerik UI for Blazor</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/blazor-ui/release-history/telerik-ui-for-blazor-13-0-0-(2026-q1)">Telerik UI for Blazor Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik UI for ASP.NET Core</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/aspnet-core-ui/2026-q1">What&rsquo;s New in Telerik UI for ASP.NET Core</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/aspnet-core-ui/release-history/telerik-ui-for-asp-net-core-2026-1-212-(2026-q1)">Telerik UI for ASP.NET Core Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik UI for ASP.NET MVC</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/aspnet-mvc/2026-q1">What&rsquo;s New in Telerik UI for ASP.NET MVC</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/aspnet-mvc/release-history/telerik-ui-for-asp-net-mvc-2026-1-212-(2026-q1)">Telerik UI for ASP.NET MVC Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik UI for ASP.NET AJAX</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/aspnet-ajax/2026-q1">What&rsquo;s New in Telerik UI for ASP.NET AJAX</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/aspnet-ajax/release-history/telerik-ui-for-asp-net-ajax-2026-1-211-(2026-q1)">Telerik UI for ASP.NET AJAX Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik UI for .NET MAUI</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/maui-ui/2026-q1">What&rsquo;s New in Telerik UI for .NET MAUI</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/maui-ui/release-history/telerik-ui-for-net-maui-13-0-0-(2026-q1)">Telerik UI for .NET MAUI Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik UI for WPF</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/wpf/2026-q1">What&rsquo;s New in Telerik UI for WPF</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/wpf/release-history/telerik-ui-for-wpf-2026-1-211-(2026-q1)">Telerik UI for WPF Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik UI for WinForms</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/winforms/2026-q1">What&rsquo;s New in Telerik UI for WinForms</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/winforms/release-history/telerik-ui-for-winforms-2026-1-210-(2026-q1)">Telerik UI for WinForms Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">ThemeBuilder</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/themebuilder/2026-q1">What&rsquo;s New in ThemeBuilder</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://docs.telerik.com/themebuilder/release-notes#11022026">ThemeBuilder Release Notes</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik Reporting</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/reporting/2026-q1">What&rsquo;s New in Telerik Reporting</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/reporting/release-history/progress-telerik-reporting-2026-q1-(20-0-26-211)">Telerik Reporting Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik Report Server</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/report-server/2026-q1">What&rsquo;s New in Telerik Report Server</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/report-server/release-history/progress-telerik-report-server-2026-q1-(12-0-26-211)">Telerik Report Server Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik Document Processing</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/document-processing-libraries">What&rsquo;s New in Telerik DPL</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/telerik-document-processing/release-history/progress-telerik-document-processing-2026-1-210">Telerik DPL Release History</a></td></tr><tr><td style="width:33.3333%;padding:5px;">Telerik JustMock</td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/justmock/2026-q1">What&rsquo;s New in Telerik JustMock</a></td><td style="width:33.3333%;padding:5px;"><a target="_blank" href="https://www.telerik.com/support/whats-new/justmock/release-history/justmock-2026-q1-(2026-1-211-494)">Telerik JustMock Release History</a></td></tr></tbody></table>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:ef2fed66-adbb-442e-90a1-a45ab5b4e2db</id>
    <title type="text">Exploring Compiled Bindings in .NET MAUI</title>
    <summary type="text">Learn about compiled bindings in .NET MAUI and how they affect performance and debugging.</summary>
    <published>2026-02-11T19:03:47Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/exploring-compiled-bindings-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Learn about compiled bindings in .NET MAUI and how they affect performance and debugging.</span></p><p>Imagine you&rsquo;re about to buy a house &hellip; but you can only discover its defects once you&rsquo;re already living in it.</p><p>You&rsquo;d definitely want to know that information beforehand to make better decisions, right? ️</p><p>The same thing happens in applications: depending on the mechanism we choose, some processes can be slower, consume more resources and&mdash;even worse&mdash;show errors way too late.</p><p>Today, you&rsquo;ll learn what <strong>Compiled Bindings</strong> are and the latest enhancements available in .NET MAUI to boost performance and avoid unpleasant surprises when the app is already in the users&rsquo; hands. </p><h2 id="data-bindings-in-.net-maui">Data Bindings in .NET MAUI</h2><p>In .NET MAUI, we usually work with <strong>data bindings,</strong> but when using them, it&rsquo;s important to keep two key points in mind:</p><ul><li><p><strong>There&rsquo;s no compile-time validation of binding expressions</strong>, which means that if a binding is invalid, we&rsquo;ll only find out when the app is already running. This can cost us valuable time, when we could have detected the issue during the compilation process.</p></li><li><p><strong>And another point</strong>, related to the one above, is that runtime verification bindings aren&rsquo;t very efficient in terms of performance, since they do all their work while the app is running.  To &ldquo;check&rdquo; the information they need, they must inspect objects over and over again. This makes the process slower and, of course, increases resource consumption.</p></li></ul><p>Compiled bindings enhance the performance of data bindings in .NET MAUI by resolving binding expressions during compile time instead of waiting until the app is running. This allows the system to detect issues early, so if a binding is incorrect, it will show up as a build error. As a result, debugging becomes easier and you avoid dealing with unexpected binding failures at runtime.</p><h2 id="compile-time-vs.-runtime-">Compile Time vs. Runtime </h2><p>We&rsquo;ve been talking a lot about compile time and runtime, so if those terms still feel a bit blurry for you, here&rsquo;s a simple explanation to make everything clearer.</p><p>➖ <strong>Compile Time:</strong> This is the moment when your code is checked to make sure everything is correct before the app can run. Here is where issues like typos in property names, missing variables, or incompatible types are detected. If something is wrong, the build stops and alerts you so you can fix it first. This saves a lot of headaches&mdash;it&rsquo;s always better to catch errors at this stage rather than later on.</p><p>➖ <strong>Runtime:</strong> This occurs when the app is already running. If an error appears at this point, it can definitely be fixed&mdash;but it may take a bit more time, since you often need to analyze more carefully to understand exactly what caused the issue. And worst of all, it can <strong>crash or freeze the app right in front of the user</strong>.</p><p>Summarizing it in a table, these would be the differences between the two:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-01/01_compiletime_and_runtime.png?sfvrsn=b1dee264_2" alt="Description: Compile Time, When does it happen? Before running the app, If there’s an error?: It stops the build and alerts you - Description: Runtime, When does it happen? While the app is running, If there’s an error? The app may crash while it’s running" /></p><h2 id="ways-to-use-compiled-bindings">Ways to Use Compiled Bindings</h2><p>There are two ways to use compiled bindings in .NET MAUI: you can apply them directly in your XAML files or configure them through C# code.</p><p>Let&rsquo;s explore each one of them:</p><h3 id="compiled-bindings-in-xaml">Compiled Bindings in XAML</h3><p>In .NET MAUI 8, compiled bindings aren&rsquo;t applied when a XAML binding uses the Source property, and they also don&rsquo;t support multi-bindings.</p><p>Starting in .NET MAUI 9, the compiler now shows warnings when bindings aren&rsquo;t using compiled bindings by default. You can learn more about this behavior in the article: <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/data-binding/compiled-bindings?view=net-maui-9.0&amp;preserve-view=true#xaml-compiled-bindings-warnings">XAML compiled binding warnings</a>.</p><h3 id="compiled-bindings-in-c-code">Compiled Bindings in C# Code</h3><p>Working with compiled bindings brings many benefits. One of the biggest ones&mdash;besides performance improvements&mdash;is that it gives us a much better experience as developers. It saves us a lot of time by showing problems <strong>before</strong> running the application. Otherwise, we would have to debug, investigate exactly where the issue happens, identify the error and then fix it. Now, IntelliSense can warn us right away.</p><p>When using bindings on C#, we normally rely on string-based property paths, such as <code>"Text"</code>.</p><p>These paths are resolved at runtime using reflection, and that process consumes resources. On top of that, the performance cost can vary depending on the platform where the app is running (Android, iOS, Windows, etc.).</p><p>Example:</p><pre class=" language-csharp"><code class="prism  language-csharp">// .NET 8
MyLabel.SetBinding(Label.TextProperty, "Text");
</code></pre><p>Now, in <strong>.NET MAUI 9,</strong> a new <code>SetBinding</code> extension method was introduced that allows defining bindings using a lambda expression (<strong>Func</strong>) instead of a string.</p><p>Like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">// .NET 9 
MyLabel.SetBinding(Label.TextProperty, static (Entry entry) =&gt; entry.Text);
</code></pre><p>When using <code>SetBinding</code>, you need to be careful with the lambda expressions you define. Only simple property access expressions are allowed. This is because compiled bindings need to know exactly which property is being bound in order to generate the optimized binding code at compile time.</p><p>A valid example would be directly accessing the <code>Name</code> property:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">static</span> <span class="token punctuation">(</span>PersonViewModel vm<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span> vm<span class="token punctuation">.</span>Name<span class="token punctuation">;</span>
</code></pre><p><strong>Besides property access, you can also use:</strong></p><p> Array or list index access</p><pre class=" language-xml"><code class="prism  language-xml">static (PersonViewModel vm) =&gt; vm.PhoneNumbers[0];
</code></pre><p> Indexer access (<code>[]</code>)</p><pre class=" language-xml"><code class="prism  language-xml">static (PersonViewModel vm) =&gt; vm.Config["Font"];
</code></pre><p> Casts to access the correct property</p><pre class=" language-xml"><code class="prism  language-xml">static (Label label) =&gt; (label.BindingContext as PersonViewModel).Name;

static (Label label) =&gt; ((PersonViewModel)label.BindingContext).Name;
</code></pre><p><strong>❌ What is not allowed?</strong></p><p>Just as it&rsquo;s important to know what is supported, it&rsquo;s equally important to understand what isn&rsquo;t. Here are some examples:</p><p>➖ Method calls</p><pre class=" language-xml"><code class="prism  language-xml">static (PersonViewModel vm) =&gt; vm.GetAddress();
</code></pre><p>➖ Creating new values by combining multiple properties</p><pre class=" language-xml"><code class="prism  language-xml">static (PersonViewModel vm) =&gt; vm.Address?.Street + " " + vm.Address?.City;
</code></pre><p>➖ String interpolation</p><pre class=" language-xml"><code class="prism  language-xml">static (PersonViewModel vm) =&gt; $"Name: {vm.Name}";
</code></pre><h2 id="bindingbase.create">BindingBase.Create</h2><p>Another improvement in .NET MAUI 9 is BindingBase.Create.</p><p>In addition to using lambda expressions directly with <code>SetBinding</code>, .NET MAUI 9 also adds a helper called <code>BindingBase.Create</code>. This is useful for more complex bindings, such as a <code>MultiBinding</code>.</p><p>Example:</p><p><strong>.NET 8</strong></p><pre class=" language-csharp"><code class="prism  language-csharp">myEntry.SetBinding(Entry.TextProperty, new MultiBinding 
{ 
    Bindings = new Collection&lt;BindingBase&gt; 
    { 
    new Binding(nameof(Entry.FontFamily), source: RelativeBindingSource.Self), 
    new Binding(nameof(Entry.FontSize), source: RelativeBindingSource.Self), 
    new Binding(nameof(Entry.FontAttributes), source: RelativeBindingSource.Self), 
    }, 
Converter = new StringConcatenationConverter()

});
</code></pre><p><strong>Now in .NET 9</strong></p><pre class=" language-csharp"><code class="prism  language-csharp">// in .NET 9

myEntry.SetBinding(Entry.TextProperty, new MultiBinding 
    { 
    Bindings = new Collection&lt;BindingBase&gt; 
    { 
    Binding.Create(static (Entry entry) =&gt; entry.FontFamily, source: RelativeBindingSource.Self), 
    Binding.Create(static (Entry entry) =&gt; entry.FontSize, source: RelativeBindingSource.Self), 
    Binding.Create(static (Entry entry) =&gt; entry.FontAttributes, source: RelativeBindingSource.Self), 
    }, 
    Converter = new StringConcatenationConverter() 
    });
</code></pre><h2 id="compiler-error">Compiler Error</h2><p>⚠️ <strong>Important:</strong> The official documentation says: &ldquo;A CS0272 compiler error will occur if the set accessor for a property or indexer is inaccessible. If this occurs, increase the accessibility of the accessor.&rdquo;</p><p><strong>Let&rsquo;s understand it in a simpler way.</strong></p><p>This error may appear when you try to assign a value to a property or indexer, but its set accessor isn&rsquo;t accessible. For example:</p><pre class=" language-csharp"><code class="prism  language-csharp">public string Name { get; private set; }
</code></pre><p>Here, the <code>Name</code> property can be read, but the set is private&mdash;so if you try to assign a value, it won&rsquo;t be possible:</p><pre class=" language-csharp"><code class="prism  language-csharp">person.Name = "Leo"; // ❌ CS0272
</code></pre><p><strong>And what would be the solution to avoid a CS0272 error?</strong> Just change the accessibility of the set so that it can be modified when needed, for example:</p><pre class=" language-csharp"><code class="prism  language-csharp">public string Name { get; set; } // ✅ Now it can be updated
</code></pre><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  Now you know what compiled bindings are, why they matter for performance and debugging, and how to use them in C#&mdash;including the enhancements introduced in .NET MAUI 9. </p><p>By applying compiled bindings, your apps become faster, more reliable and much easier to troubleshoot &hellip; before your users ever see an error. I hope this guide helps you improve the quality and performance of your applications starting today!</p><p>If you have any questions or want to see more related topics, feel free to leave them in the comments&mdash;I&rsquo;d love to help you! </p><p>See you in the next article! &zwj;♀️</p><h3 id="references">References</h3><p>The explanation was based on the official documentation, and includes most of the code examples presented there.</p><ul><li><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/whats-new/dotnet-9?view=net-maui-9.0">https://learn.microsoft.com/en-us/dotnet/maui/whats-new/dotnet-9?view=net-maui-9.0</a></li></ul><aside><hr data-sf-ec-immutable="" /><div class="row"><div class="col-4 u-normal-full u-small-mb0"><h4 class="u-fs20 u-fw5 u-lh125 u-mb0">Adding External Fonts in .NET MAUI</h4></div><div class="col-8"><p class="u-fs16 u-mb0">Change your font, change your app. Here&rsquo;s how to use an <a target="_blank" href="https://www.telerik.com/blogs/adding-external-fonts-net-maui">external font inside your .NET MAUI</a> app to match your branding and style.</p></div></div></aside>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:f52458cd-0570-40b3-9484-6fac69dafe2c</id>
    <title type="text">Replicating a Valentine-Inspired Login UI in .NET MAUI</title>
    <summary type="text">Learn how to build a Valentine-inspired login interface with .NET MAUI. We’ll go through the process step by step!</summary>
    <published>2026-02-05T16:49:46Z</published>
    <updated>2026-05-25T00:09:58Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://www.telerik.com/blogs/replicating-valentine-inspired-login-ui-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Learn how to build a Valentine-inspired login interface with .NET MAUI. We&rsquo;ll go through the process step by step!</span></p><p>We find love in many forms: in the people around us, in that hobby we enjoy so much, in wearing clothes that make us feel good &hellip; and also in every step of our professional growth.</p><p>Yes, even in that love for creating beautiful, functional and well-thought-out user interfaces using XAML.</p><p>For many, designing UI can be a challenge. But like everything in development, that challenge is overcome by learning, practicing and daring to create. That&rsquo;s why in this article we&rsquo;re going to build a Valentine&rsquo;s-inspired UI, taking as reference a design found on <a target="_blank" href="https://dribbble.com/shots/22000659-Sign-in-Sign-up-UI-design-Valentine-s-Day-Style">Dribbble</a> and adapting it into an implementation using .NET MAUI.</p><p>We&rsquo;ll build step by step a registration and a login screen. We&rsquo;ll break down each section with its corresponding code blocks, so you can walk away not only with a visually appealing interface, but also with practical ideas you can apply to your own projects.</p><p>So get ready, because today we&rsquo;re putting a little love into code. ❤️</p><h2 id="explanation--insights">Explanation &amp; Insights</h2><p>Before we get started, let&rsquo;s go over a few key points that will help you better understand and replicate the UI:</p><ul><li><strong>Visual guide:</strong> Before we begin, I&rsquo;ll share a preview of the UI we want to achieve. This image will be divided into color-coded blocks to make it easier to identify each section throughout the article.</li><li><strong>Code blocks:</strong> Each block will be explained separately. Every section will include a textual explanation, a code snippet with the exact code you need to write to achieve the result, and a screenshot showing how the UI evolves step by step.</li><li><strong>No styles:</strong> For the moment, we won&rsquo;t use styles. This way, even developers who are just starting to build UIs can follow along more easily and understand the core structure without extra complexity. ❤️</li></ul><h2 id="breaking-down-the-dribbble-design-into-blocks">Breaking Down the Dribbble Design into Blocks</h2><p>To make this easier to follow, I&rsquo;ve divided the original design into clear blocks. We&rsquo;ll build each part one at a time, in the order you see below.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-01/01_main_structure.png?sfvrsn=5241b8a5_2&amp;Culture=en" /></p><h2 id="main-structure">Main Structure</h2><p>To create the first screen, we&rsquo;ll start by creating a file called SignInPage.xaml. This file will contain the elements corresponding to blocks one and two of the block-based structure shown earlier.</p><p>Before we begin adding elements, it&rsquo;s important to define an efficient structure, and this is where the layout comes into play. Choosing the right layout allows us to organize elements more easily within the screen. Since this is a simple example with a single vertical column of elements, we&rsquo;ll use VerticalStackLayout as the main layout.</p><p>The <strong>VerticalStackLayout</strong> allows the elements to be vertically centered. Additionally, I added <strong>30 of horizontal padding</strong> and a <strong>spacing of 40</strong> between all the elements contained on this screen.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;ScrollView&gt; 
    &lt;VerticalStackLayout 
    VerticalOptions="Center" 
    Padding="30,0" 
    Spacing="40"&gt;
     
    &lt;!-- Add all the code here &rarr;
     
    &lt;/VerticalStackLayout&gt; 
&lt;/ScrollView&gt;
</code></pre><p> <strong>Tip:</strong> We&rsquo;ll also wrap this layout inside a ScrollView, so that on devices with smaller screens, users can scroll through the content without it being cut off or overflowing the screen.</p><p>If you want to know more information about VerticalStackLayout, I invite you to read the article <a target="_blank" href="https://www.telerik.com/blogs/exploring-layout-options-dotnet-maui">Exploring Layout Options in .NET MAUI</a>.</p><p><strong>Adding a background to the ContentPage:</strong> To give the page a uniform background color, we add the <strong>BackgroundColor</strong> property to the <strong>ContentPage</strong> and assign it the value <strong>#FFF8F8</strong>.</p><h2 id="header-block">Header Block</h2><p>Now we&rsquo;re ready! Let&rsquo;s start building the first block.</p><p>Before creating a UI, I like to analyze all the elements that make it up. This helps me clearly identify which components I&rsquo;ll need and avoid having to rewrite code later on.</p><p>In this first block, the elements we see on the screen are:</p><ul><li>A horizontally centered image &rarr; we&rsquo;ll use an <code>&lt;Image&gt;</code> component</li><li>A red title &rarr; we&rsquo;ll use a <code>&lt;Label&gt;</code></li><li>A description or subtitle in black &rarr; we&rsquo;ll use a <code>&lt;Label&gt;</code></li></ul><p>Let&rsquo;s start by adding the image </p><pre class=" language-xml"><code class="prism  language-xml">&lt;Image 
    Source="heart" 
    HeightRequest="100" 
    Aspect="AspectFit" 
    SemanticProperties.Description="Header image" /&gt;

&lt;!-- Add the next code block below --&gt;
</code></pre><p>Here are a few important points to highlight:</p><p>➖ <strong>AspectFit:</strong> We added the image using the <strong>Aspect</strong> property with the value <strong>AspectFit</strong>, which allows the image to fit entirely within the available display area without being distorted. You can learn more about the differences between the various <a target="_blank" href="https://askxammy.com/image-scaling-in-net-maui/">image aspect options in this article</a>.</p><p>➖ <strong>SemanticProperties:</strong> We added a <strong>semantic description</strong>, which helps screen readers understand what element is being displayed on the screen. You can read more about this topic in the article <a target="_blank" href="https://www.telerik.com/blogs/creating-accessible-apps-semantic-properties-dotnet-maui">Creating Accessible Apps with Semantic Properties in .NET MAUI</a>.</p><p>Let&rsquo;s continue adding the Label with the title:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label 
    Text="Sign In" 
    FontSize="20" 
    FontAttributes="Bold" 
    TextColor="#d14361" 
    SemanticProperties.Description="Sign In" /&gt; 
&lt;!-- Add the next code block below --&gt;
</code></pre><p>And to finish this first block, let&rsquo;s add the description or subtitle:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label 
    Text=&rdquo;Welcome! Please sign in to access your account and explore a world of possibilities." 
    TextColor="#121111" 
    FontSize="15" 
    SemanticProperties.Description="Welcome!"/&gt; 
&lt;!-- Add the next code block below --&gt;
</code></pre><p><strong>At this point, your UI should look similar to the following example:</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-01/03_block_01_demo.png?sfvrsn=fd0748c5_2&amp;Culture=en" /></p><h2 id="sign-in-content-block">Sign-in Content Block</h2><p>Continuing with the second block, let&rsquo;s take a look at the elements that make up this component:</p><ul><li><strong>Two input fields:</strong> One for the username and one for the password</li><li><strong>Two buttons:</strong> The first with the fields, &ldquo;Login&rdquo;; and the second for &ldquo;Create an account&rdquo;</li><li><strong>Two labels:</strong> One for the &ldquo;Forgot your password&rdquo; message and another for &ldquo;Don&rsquo;t have an account&rdquo;</li></ul><p>Let&rsquo;s start with the two fields for the username and password </p><p>Here, in addition to the username <strong>Entry</strong>, we add a password <strong>Entry</strong> and set the <strong>IsPassword</strong> property to <strong>True</strong> so the characters are hidden as the user types.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Entry Placeholder="Username"/&gt; 
&lt;Entry IsPassword="True" Placeholder="Password"/&gt;
&lt;!-- Add the next code block below --&gt;
</code></pre><h3 id="the-login-button">The Login Button</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Button BackgroundColor="#d14361" 
    CornerRadius="50" 
    FontAttributes="Bold" 
    HeightRequest="50" 
    Text="LOGIN"/&gt;
&lt;!-- Add the next code block below --&gt;
</code></pre><h3 id="forgot-your-password-label">Forgot Your Password Label</h3><p>This text is composed of two different styles, and since a simple <strong>&lt;Label&gt;</strong> cannot handle multiple styles at the same time, we&rsquo;ll use <strong>&lt;Label.FormattedText&gt;</strong> to achieve this.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label&gt; 
    &lt;Label.FormattedText&gt; 
    &lt;FormattedString&gt; 
    &lt;Span Text="Forgot password? " TextColor="#555351" /&gt; 
    &lt;Span Text=" Reset here" TextColor="#d14361" FontAttributes="Bold"/&gt; 
    &lt;/FormattedString&gt; 
    &lt;/Label.FormattedText&gt; 
&lt;/Label&gt; 
&lt;!-- Add the next code block below --&gt;
</code></pre><h3 id="don’t-have-an-account-label">Don&rsquo;t Have an Account Label</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text=" Don't have an account?" 
    HorizontalOptions="Center" 
    TextColor="Gray"/&gt; 
&lt;!-- Add the next code block below --&gt;
</code></pre><h3 id="create-an-account-button">Create an Account Button</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Button BackgroundColor="#9A8687" 
    CornerRadius="50" 
    HeightRequest="50" 
    FontAttributes="Bold" 
    Text="CREATE AN ACCOUNT"/&gt;
</code></pre><p><strong>And that&rsquo;s it!</strong>  We&rsquo;ve completed this second section, which means the first screen is now finished. At this point, your result should look like the following:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-01/05_block_02_demo.png?sfvrsn=f6f6d484_2&amp;Culture=en" /></p><h2 id="create-account-page">Create Account Page</h2><p>We&rsquo;ve reached the final stretch! And the last screen! </p><p>Since this is a new screen, we&rsquo;ll create a file called CreateAccountPage.xaml. Just like on the previous screen, we&rsquo;ll use a VerticalStackLayout as the main layout.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;ScrollView&gt; 
    &lt;VerticalStackLayout 
    VerticalOptions="Center" 
    Padding="30,0" 
    Spacing="40"&gt; 
    
    &lt;!-- Add all the code here &rarr;
     
    &lt;/VerticalStackLayout&gt; 
&lt;/ScrollView&gt;
</code></pre><p>✍️ Here, we will also add the <strong>BackgroundColor</strong> property to the ContentPage, setting its value to <strong>#FFF8F8</strong>.</p><p>This screen contains several elements&mdash;let&rsquo;s start with the title and the description labels:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label 
    Text="Create an account" 
    FontSize="20" 
    FontAttributes="Bold" 
    TextColor="#d14361"/&gt; 
    
&lt;Label 
    Text="Join us on an exciting journey! Create your account and embark on a path filled with discovery and opportunities." 
    TextColor="#121111" 
    FontSize="15"/&gt;

&lt;!-- Add the next code block below --&gt;
</code></pre><p>Let&rsquo;s continue with the username, email and password input fields. To keep this example simple, we won&rsquo;t add a show/hide password feature.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Entry Placeholder="Username"/&gt;

&lt;Entry Placeholder="Email"/&gt;

&lt;Entry IsPassword="True" Placeholder="Password"/&gt;
</code></pre><p>Finally, let&rsquo;s add a button, text for the terms and conditions, and another button to navigate to the Sign Up action.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button BackgroundColor="#d14361" 
    CornerRadius="50" 
    FontAttributes="Bold" 
    HeightRequest="50" 
    Text="SIGN UP"/&gt;
 
&lt;Label&gt; 
    &lt;Label.FormattedText&gt; 
    &lt;FormattedString&gt; 
    &lt;Span Text="By tapping 'Sign In' you accept out " TextColor="#555351" /&gt; 
    &lt;Span Text=" terms" TextColor="#d14361" FontAttributes="Bold"/&gt; 
    &lt;Span Text=" and " TextColor="#555351" /&gt; 
    &lt;Span Text=" conditions" TextColor="#d14361" FontAttributes="Bold"/&gt; 
    &lt;/FormattedString&gt; 
    &lt;/Label.FormattedText&gt; 
&lt;/Label&gt;
 
&lt;Label&gt; 
    &lt;Label.FormattedText&gt; 
    &lt;FormattedString&gt; 
    &lt;Span Text="Already have an account? " TextColor="#555351" /&gt; 
    &lt;Span Text=" Sign Up here" TextColor="#d14361" FontAttributes="Bold"/&gt; 
    &lt;/FormattedString&gt; 
    &lt;/Label.FormattedText&gt; 
&lt;/Label&gt;
</code></pre><p>And the final result should look like the following:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-01/07_block_03_demo.png?sfvrsn=cc66a46c_2&amp;Culture=en" /></p><p>With these simple steps, you&rsquo;ve learned how to work with various .NET MAUI components and have successfully built your first two screens! </p><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, we explored how to build a Valentine-inspired login and sign-up UI using .NET MAUI with XAML. By breaking the UI into clear blocks and working step by step, you were able to focus on layout, and components without adding unnecessary complexity.</p><p>Remember, creating beautiful interfaces is not just about visuals&mdash;it&rsquo;s about crafting experiences users will enjoy interacting with.</p><p>If you have any questions or would like me to dive deeper into specific topics, feel free to leave a comment&mdash;I&rsquo;ll be happy to help! </p><p>See you in the next article! &zwj;♀️</p><aside><hr data-sf-ec-immutable="" /><div class="row"><div class="col-4 u-normal-full u-small-mb0"><h4 class="u-fs20 u-fw5 u-lh125 u-mb0">6 .NET MAUI Properties You Didn&rsquo;t Know Work with Buttons</h4></div><div class="col-8"><p class="u-fs16 u-mb0">Learn several useful properties to help you customize and enhance your <a target="_blank" href="https://www.telerik.com/blogs/6-net-maui-properties-you-didnt-know-work-buttons"> buttons in .NET MAUI</a>, like rounding the corners buttons and enabling automatic scaling.</p></div></div></aside>]]></content>
  </entry>
</feed>
