<?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>
  <link rel="hub" href="https://feedpress.superfeedr.com/"/>
  <logo>https://static.feedpress.com/logo/telerik-blogs-mobile-net-maui-6185107a1dcff.jpg</logo>
  <title type="text">Telerik Blogs | Mobile| .NET MAUI</title>
  <subtitle type="text">The official blog of Progress Telerik - expert articles and tutorials for developers.</subtitle>
  <id>uuid:d536280c-5815-417a-ba64-256497ab1ae3;id=1175</id>
  <updated>2026-07-12T06:22:21Z</updated>
  <link rel="alternate" href="https://www.telerik.com/"/>
  <link rel="self" type="application/atom+xml" href="https://feeds.telerik.com/blogs/mobile-net-maui"/>
  <entry>
    <id>urn:uuid:3688cfa4-c260-412e-918e-9889e5046f2a</id>
    <title type="text">Available Now in .NET 11 for .NET MAUI</title>
    <summary type="text">Explore the .NET 11 updates available now in .NET MAUI, including map enhancements, long press recognition, animation improvements and more.</summary>
    <published>2026-07-08T15:35:21Z</published>
    <updated>2026-07-12T06:22:21Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17374971/available-now-net-11-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Explore the .NET 11 updates available now in .NET MAUI, including map enhancements, long press recognition, animation improvements and more.</span></p><p>Oh yeahhh!!  .NET 11 for .NET MAUI is here!</p><p>And, as always, my recommendation is to stay up to date with every new release. What changed? What&rsquo;s new? What has been improved? Keeping up with these updates helps us build better apps and keeps our code inline with the latest recommendations from the Microsoft team.</p><p>For .NET 11, the team&rsquo;s main focus has been improving the overall quality of .NET MAUI, making it faster and easier for us as developers, to build amazing applications. In this article, you&rsquo;ll discover some of my favorite improvements that Microsoft has introduced for .NET MAUI in .NET 11!</p><h2 id="maps-improvements">1. Maps Improvements</h2><p>This is one of my favorite updates in .NET 11!  Let&rsquo;s start by exploring the <strong><a target="_blank" href="https://learn.microsoft.com/es-es/dotnet/api/microsoft.maui.controls.maps.map?view=net-maui-10.0">Map</a></strong> control, which has received some really nice improvements. Here are some of the highlights!</p><h3 id="pin-clustering">Pin Clustering</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-07/01_improvement_map.png?sfvrsn=9f323c91_2" title=".NET MAUI 11 Map Improvement: Pin Clustering" alt="Illustrated maps. Without clustering the pins, they are everywhere. With clustering enabled, blue circles have numbers for how many pins are in that area" /><br /><span style="font-size:11px;">For educational purposes, this image was generated with AI</span></p><p>Imagine you&rsquo;re building a restaurant app where users can view nearby restaurants on a map. You may have <strong>300, 400 or even more locations</strong> to display. If the user opens the map while zoomed out, it could look something like this: </p><p>This quickly becomes overwhelming because many pins overlap, making it difficult to select a specific location.</p><p>With <strong>.NET 11,</strong> you can simply use this property:</p><pre class=" language-xml"><code class="prism  language-xml">IsClusteringEnabled="True"
</code></pre><p>And with that, .NET MAUI will automatically group nearby pins into clusters. So instead of displaying multiple overlapping pins like , users will see something like (5), indicating that five locations are grouped together.</p><p>As users zoom in, those clusters gradually split into individual pins, creating a much cleaner experience and making it much easier to interact with the map.</p><p>Using it in .NET MAUI is incredibly simple:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;maps:Map IsClusteringEnabled="True"

    ClusterClicked="OnClusterClicked" /&gt;
</code></pre><h3 id="custom-location-markers">Custom Location Markers</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-07/02_improvement_map.png?sfvrsn=74e1d38_2" title=".NET MAUI 11 Map Improvement: Custom Location Markers" alt="Illustrated maps showing custom location markers for hospitals and pharmacies, instead of the simple pin" /><br /><span style="font-size:11px;">For educational purposes, this image was generated with AI</span></p><p>Yay!!  Another great addition is the ability to <strong>customize your map markers</strong>.</p><p>Instead of using the default pin for every location, you can now display a custom image for each marker, making your maps much more intuitive and visually appealing.</p><p>For example, imagine you&rsquo;re building a healthcare app. You could use one icon for <strong>hospitals</strong> and a different one for <strong>pharmacies</strong>, allowing users to quickly identify each type of location without even reading the labels.</p><p>This is possible by simply setting the <strong>ImageSource</strong> property on the pin.</p><p>Here&rsquo;s what it looks like in code:</p><pre class=" language-csharp"><code class="prism  language-csharp">var pin = new Pin
{ 
    Label = "Custom pin", 
    Location = new Location(18.4861, -69.9312), 
    ImageSource = ImageSource.FromFile("hospitals.png") 
};
</code></pre><h3 id="json-map-style-android">JSON Map Style (Android)</h3><p>Google Maps allows you to customize the map using a JSON file. This means you can change colors, switch between light and dark mode, customize labels and much more.</p><p>Previously, this was much more complicated in .NET MAUI. Now, all you have to do is assign your JSON file to the <strong>MapStyle</strong> property, and you&rsquo;re done! </p><h2 id="cancel-animations-with-cancellationtoken">2. Cancel Animations with CancellationToken</h2><p>This improvement may seem small, but it&rsquo;s actually a very useful one, especially when you have multiple animations running at the same time.</p><p>Before .NET 11, if you started an animation and later wanted to stop it, your only option was to do something like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">image.CancelAnimations();
</code></pre><p>However, there was a small problem.  This method <strong>canceled every animation</strong> running on that control.</p><p>Imagine your image is running two animations simultaneously: a rotation animation and a fade animation. If you only wanted to stop the rotation while keeping the fade animation running, that simply wasn&rsquo;t possible.</p><p>Starting with .NET 11, the animation methods now optionally accept a <strong>CancellationToken</strong>. This means you can cancel a specific animation without affecting the others.</p><p>For example:</p><pre class=" language-csharp"><code class="prism  language-csharp">var cts = new CancellationTokenSource();

await image.FadeToAsync( 
opacity: 0, 
cancellationToken: cts.Token);
</code></pre><p>And when you want to stop that animation:</p><pre class=" language-csharp"><code class="prism  language-csharp">cts.Cancel();
</code></pre><p>That&rsquo;s it! Only the animation associated with that <strong>CancellationToken</strong> will be canceled, while any other animations on the same control will continue running normally.</p><h3 id="methods-without-async-are-now-obsolete">Methods Without Async Are Now Obsolete</h3><p>Another important change is that animation methods without the <strong>Async</strong> suffix have now been marked as obsolete. Methods such as <strong>FadeTo(), RotateTo() and ScaleTo()</strong> are now marked as <strong>[Obsolete].</strong> Instead, Microsoft recommends using their asynchronous counterparts:</p><ul><li>await FadeToAsync(&hellip;);</li><li>await RotateToAsync(&hellip;);</li><li>await ScaleToAsync(&hellip;);</li></ul><p>Of course, these methods also support the new <strong>CancellationToken</strong>, giving you much greater control over your animations.</p><h2 id="longpressgesturerecognizer">3. LongPressGestureRecognizer</h2><p>Have you noticed that some actions in mobile apps are only triggered when you press and hold a control for some seconds? Thanks to <strong>.NET 11</strong>, .NET MAUI now includes the <strong>LongPressGestureRecognizer</strong>, making it easy to detect this gesture.</p><p>It provides several useful features:</p><ul><li>Detects long-press gestures</li><li>Configurable press duration</li><li>Movement threshold to cancel the gesture if the finger moves too far</li><li>Gesture state tracking through GestureState</li><li>Support for Command and CommandParameter</li></ul><p>Using it is as simple as this:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Image Source="flower.png"&gt; 
&lt;Image.GestureRecognizers&gt; 
&lt;LongPressGestureRecognizer 
    Duration="500" 
    LongPressed="OnLongPressed"/&gt; 
    &lt;/Image.GestureRecognizers&gt; 
&lt;/Image&gt;
</code></pre><p>The event:</p><pre class=" language-csharp"><code class="prism  language-csharp">void OnLongPressed(object sender, LongPressGestureRecognizerEventArgs e) 
{ 
    if (e.State == GestureState.Completed) 
    { 
    // Your code goes here 
    } 
}
</code></pre><h2 id="we-can-finally-use-gradients-in-boxview">4. We Can Finally Use Gradients in BoxView!</h2><p>BoxView is a super useful control that gives us a lot of flexibility when building UI. However, before .NET 11, it had one important limitation: <strong>it could only display a solid color.</strong> So, if you wanted a gradient, you had to rely on other controls or custom solutions.</p><p>With .NET 11, BoxView now includes the Fill property, which is of type Brush. This means you can finally apply gradients directly to a BoxView! And don&rsquo;t worry, if you only need a solid color, you can continue using the BackgroundColor property as before.</p><p>Here&rsquo;s a simple example:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;BoxView HeightRequest="260"&gt; 
    &lt;BoxView.Fill&gt; 
    &lt;LinearGradientBrush&gt; 
    ... 
    &lt;/LinearGradientBrush&gt; 
    &lt;/BoxView.Fill&gt; 
&lt;/BoxView&gt;
</code></pre><h2 id="trimmable-css">5. Trimmable CSS</h2><p>I don&rsquo;t know if you knew this, but .NET MAUI has supported CSS for quite some time. The problem was that even if your application didn&rsquo;t use CSS, .NET MAUI still had to include all the infrastructure required to support it, increasing the final size of your app.</p><p>With .NET 11, that&rsquo;s no longer the case. If your application doesn&rsquo;t use CSS stylesheets, the CSS infrastructure is automatically removed during the publishing process. In short, if you don&rsquo;t use CSS, your application becomes smaller <strong>without you having to do anything</strong>.</p><h2 id="material-3-on-android">6. Material 3 on Android</h2><p>Previously, some .NET MAUI controls on Android were not fully aligned with Material 3. Starting with .NET 11 Preview 4, several Android handlers now use <strong>Material 3</strong> by default. This applies to controls such as:</p><ul><li>ImageButton</li><li>DatePicker</li><li>Entry</li><li>Slider</li></ul><p>In short, it was common to find controls that didn&rsquo;t fully follow Android&rsquo;s modern design guidelines. With .NET 11, that changes. These controls are now much more aligned with Material 3, resulting in a more modern, consistent look that feels fully integrated with the Android ecosystem. </p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-07/03_improvement_material_controls.png?sfvrsn=9620bef2_2" title=".NET MAUI 11 Material 3 on Android" alt="Material 3 on Android in dark and light mode on .NET MAUI now in >NET 11" /><br /><span style="font-size:11px;">Image obtained from the official documentation</span></p><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it! I hope this article helps you discover some of the exciting new features coming to .NET MAUI with .NET 11.</p><p>Throughout this article, we explored some of my favorite improvements, including the new LongPressGestureRecognizer, Map enhancements, BoxView gradients, animation improvements and Android Material 3 support.</p><p>Of course, these are just a few of my favorites! I encourage you to explore the article &ldquo;<a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/whats-new/dotnet-11?view=net-maui-10.0">What&rsquo;s new in .NET MAUI for .NET 11</a>&rdquo; from the official documentation to discover even more improvements and enhancements included in this release.</p><p>I also encourage you to keep experimenting with these new features and continue learning something new every day. </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">What&rsquo;s New for Blazor in .NET 11 Preview Releases 1 and 2</h4></div><div class="col-8"><p class="u-fs16 u-mb0">Tour the <a target="_blank" href="https://www.telerik.com/blogs/whats-new-blazor-net-11-preview-releases-1-2">notable Blazor changes and new features in .NET 11 Previews 1 and 2</a> for an early glimpse into what&rsquo;s coming for Blazor in .NET 11.</p></div></div></aside><img src="https://feeds.telerik.com/link/23059/17374971.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:679fe682-4514-4e7a-94ff-ef3f94efed17</id>
    <title type="text">Replicating a Travel App in .NET MAUI</title>
    <summary type="text">Practice thoughtful planning before you begin coding with this .NET MAUI travel app. We’ll divide the design into blocks and code each one.</summary>
    <published>2026-07-01T16:48:23Z</published>
    <updated>2026-07-12T06:22:21Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17371196/replicating-travel-app-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Practice thoughtful planning before you begin coding with this .NET MAUI travel app. We&rsquo;ll divide the design into blocks and code each one.</span></p><p>Take note of this: always&mdash;always&mdash;absolutely always&mdash;when you start developing an app, take a moment to step back and analyze what you truly need. That way, you avoid writing the same code two, three or even N times.</p><p>Once you begin, aim to keep your code as clean and optimized as possible. Remember that every component you choose is a decision that shapes the quality of your app from the layout you select (where everything begins) to the components you use and the reasoning behind them. And of course, becoming more comfortable with XAML every day is key. With creativity and a willingness to think outside the box, anything can be achieved in a UI.</p><p>With practice, this process becomes easier, as experience gives you the insight needed to make faster and more confident decisions. That&rsquo;s why in this article we will replicate a travel UI from scratch, inspired by a design obtained from <a target="_blank" href="https://dribbble.com/shots/26145161-Travel-app-design">Dribbble</a>.</p><p><strong>How will the explanation work?</strong></p><p>So you can understand everything 100%, I&rsquo;ll explain how the process will work:</p><p>➖<strong>Visual diagram:</strong> Before we start, you&rsquo;ll see a diagram with a screenshot of the design we want to achieve. This design will be divided into blocks, each identified with a name and a color. Each block will be explained individually.</p><p>➖<strong>Code explanation per block:</strong> In addition to the text explanation, each block will include the exact code snippet you need to write to achieve the result.</p><p>➖<strong>Step-by-step visual progress:</strong> Each explanation will have its corresponding screenshot, so you can see the progress as we build the UI.</p><p>⚠️ For the purposes of these articles, there will be some changes to the original user interface.</p><h2 id="-environment-setup"> Environment Setup</h2><p>You&rsquo;ll learn how to take advantage of some of the powerful components provided in the Progress Telerik UI for <a target="_blank" href="https://www.telerik.com/maui-ui">.NET MAUI component library</a>. Before we dive in, let&rsquo;s get your environment ready, just keep these two key points in mind:</p><ol><li><p><strong>If you don&rsquo;t have a <a target="_blank" href="https://www.telerik.com/account/">Telerik account</a> yet, you can create one for free.</strong> You&rsquo;ll get access to a trial license so you can explore not only RadBorder and RadButton, but all the Telerik controls for .NET MAUI.</p></li><li><p><strong>You need to install Telerik UI for .NET MAUI.</strong> This is a one-time setup, meaning you don&rsquo;t need to do it for every component you use. (If you don&rsquo;t have it installed yet, I&rsquo;ve included an article where it is explained step by step how to set it up in both <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/first-steps-vs">Visual Studio</a> and <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/first-steps-vs-code">Visual Studio Code</a>.)</p></li></ol><h2 id="breaking-down-the-design-into-blocks">Breaking Down the Design into Blocks</h2><p>To make this easier to follow, I&rsquo;ve divided the 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-06/01_visual_structure.png?sfvrsn=6c886051_2" title="Visual structure" alt=".NET MAUI travel app structure" /></p><p>Alright, we&rsquo;ve now divided our UI into blocks. Grab a cup of coffee (or hot chocolate), and let&rsquo;s start writing some code! </p><h2 id="main-image">1. Main Image</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/02_main_image_block.png?sfvrsn=308faa3_2" title="Main imagen block" alt=".NET MAUI travel app main image" /></p><p>When starting to build a UI, the first thing you should evaluate is which layout best fits your needs. In this case, we need a flexible layout that allows us to create overlapping effects both for positioning text on top of the image and for building the overlapping effect in the second block.</p><p>For this, we&rsquo;ll use a Grid, structured as follows:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid RowDefinitions="auto,*"&gt;  
    &lt;!-- Place here the remaining elements that belong to the first block--&gt; 
    &lt;!-- Insert here the code for the next block --&gt;     
&lt;/Grid&gt;
</code></pre><p>Now, let&rsquo;s add the main image along with the two text elements displayed on top of it. Place this code in the section indicated by the comment: <code>&lt;!-- Place here the remaining elements that belong to the first block --&gt;</code>.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Image Grid.Row="0" Source="homebg" Aspect="Fill" HeightRequest="500"/&gt; 

&lt;Label Grid.Row="0" Text="Wanna Go List" TextColor="White" FontSize="24" FontAttributes="Bold" 
    TranslationY="-40" 
    HorizontalTextAlignment="Center" 
    VerticalTextAlignment="Center"/&gt; 

&lt;Label Grid.Row="0" Text="Save only your favorite hotels.&amp;#10;Search only your favorite hotels." 
    TextColor="White" FontSize="17" TranslationY="-65" 
    HorizontalTextAlignment="Center" 
    VerticalTextAlignment="End"/&gt;
</code></pre><p>✍️ To help create the overlapping effect across the Grid areas, I used the <code>TranslationY</code> property to position the element exactly where needed.</p><h2 id="sign-in-details">2. Sign-in Details</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/03_sign_in_details_block.png?sfvrsn=d4b404c0_2" title="Sign In details block" alt=".NET MAUI travel app sign in" /></p><p>For this second block, we&rsquo;ll work with several elements, all contained within a white background with rounded top corners. This is where Telerik RadBorder plays a key role.</p><p>Inside this container, we&rsquo;ll include:</p><ul><li>Rounded and rectangular buttons (using Telerik RadButton)</li><li>Simple labels and styled text (using FormattedText)</li></ul><h3 id="white-background-with-rounded-corners">White Background with Rounded Corners</h3><p>To get started with RadBorder, add the corresponding namespace:</p><pre class=" language-xml"><code class="prism  language-xml">xmlns:telerik="clr-namespace:Telerik.Maui.Controls;assembly=Telerik.Maui.Controls"
</code></pre><p>Once that&rsquo;s set up, add the component as shown below.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadBorder Grid.Row="1" 
    BackgroundColor="White" 
    VerticalOptions="Fill" 
    Margin="0,-40,0,0" 
    CornerRadius="30" 
    Padding="30"&gt; 
    &lt;!-- Add the Grid here-- &gt; 
&lt;/telerik:RadBorder&gt;
</code></pre><p>Inside the RadBorder, we&rsquo;ll use a Grid to structure the content. This Grid will consist of four rows and three columns, with a spacing of 20 between elements to maintain a clean and well-organized layout.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid RowDefinitions="auto,auto,auto,auto" ColumnDefinitions="*,*,*" RowSpacing="20"&gt; 
    &lt;!-- Add all remaining elements for the second block here --&gt; 
&lt;/Grid&gt;
</code></pre><p>Finally, let&rsquo;s add all the remaining elements inside the Grid. Here are a few key points to keep in mind:</p><p>➖ For the buttons, we&rsquo;ll use Telerik RadButton. Since you already added the namespace earlier, there&rsquo;s no need to include it again.</p><p>➖ To achieve a rounded button, simply set the <code>WidthRequest</code> and <code>HeightRequest</code> to the same value, and define the <code>CornerRadius</code> as half of that value.</p><p>➖ For the label with multiple colors, instead of using several separate labels, we&rsquo;ll use <code>FormattedText</code>. This helps keep the code cleaner and more efficient.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadButton Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Text="Sign In Via Email" TextColor="White" BackgroundColor="#0c538f" CornerRadius="8"/&gt;

&lt;Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Text="or sign in with" FontSize="13" HorizontalTextAlignment="Center" TextColor="Grey"/&gt;

&lt;telerik:RadButton Grid.Row="2" Grid.Column="0" ImageSource="google" BackgroundColor="#def0f5" HeightRequest="60" WidthRequest="60" CornerRadius="30" HorizontalOptions="End"/&gt;
 
&lt;telerik:RadButton Grid.Row="2" Grid.Column="1" ImageSource="apple" BackgroundColor="#def0f5" HeightRequest="60" WidthRequest="60" CornerRadius="30"/&gt;
 
&lt;telerik:RadButton Grid.Row="2" Grid.Column="2" ImageSource="facebook" BackgroundColor="#def0f5" HeightRequest="60" WidthRequest="60" CornerRadius="30" HorizontalOptions="Start"/&gt;
 
&lt;Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" HorizontalTextAlignment="Center"&gt;

&lt;Label.FormattedText&gt; 
    &lt;FormattedString&gt; 
    &lt;Span Text="Don't have an account? " TextColor="Grey"/&gt; 
    &lt;Span Text="Sign Up" FontAttributes="Bold" TextColor="#0c538f"/&gt; 
    &lt;/FormattedString&gt; 
    &lt;/Label.FormattedText&gt; 
&lt;/Label&gt;
</code></pre><h2 id="header">3. Header</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/04_header_block.png?sfvrsn=77918cc2_2" title="Header block" alt=".NET MAUI travel app header" /></p><p>Woohoo!!!  Our first screen is ready.  Now, in this third block, we&rsquo;ll start building the second screen packed with some really interesting elements!</p><p>Let&rsquo;s begin with the main layout. We&rsquo;ll create a three row Grid where we&rsquo;ll position the header image, a VerticalStackLayout to hold the plans and benefits and the footer.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid RowDefinitions="auto,*,auto,auto" RowSpacing="20" Padding="20,0"&gt; 
    &lt;!-- Add the header image code here --&gt; 
    &lt;!-- Add the VerticalStackLayout here &rarr; 
    &lt;!-- Add the footer code here --&gt; 
&lt;/Grid&gt;
</code></pre><p>To get started, we&rsquo;ll focus on placing the header image and the primary label.</p><h3 id="header-image">Header Image</h3><p>You can either use an image that already has a diagonal effect or take a regular image and create that effect through code. For this demo, I used a regular image and rotated it to show you how it works. This effect comes from combining <code>Rotation</code>, <code>TranslationY</code>, and <code>TranslationX</code> properties, along with adjusting the width and height.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Image Grid.Row="0" Source="header" HeightRequest="370" WidthRequest="500" Aspect="AspectFit" 
    Rotation="-15" 
    TranslationX="-20" 
    TranslationY="-300"/&gt;
</code></pre><h3 id="main-label">Main Label</h3><p>Before adding the label itself, we&rsquo;ll set up the layout that will contain it. Add a VerticalStackLayout, and inside it place a Label with FormattedText. This allows you to apply different colors, sizes and styles within a single label, keeping your UI clean and flexible.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;VerticalStackLayout Grid.Row="0" Margin="0,140,0,0"&gt; 
&lt;Label HorizontalTextAlignment="Center" FontSize="28" CharacterSpacing="18"&gt; 
&lt;Label.FormattedText&gt; 
    &lt;FormattedString&gt; 
    &lt;Span Text="Unlock " FontAttributes="Bold"/&gt; 
    &lt;Span Text="Pro&amp;#10;" FontAttributes="Bold" TextColor="#4b9db4"/&gt; 
    &lt;Span Text="Features! " FontAttributes="Bold"/&gt; 
    &lt;/FormattedString&gt; 
&lt;/Label.FormattedText&gt; 
&lt;/Label&gt;
 
&lt;!-- Add the Benefits code block here --&gt; 
&lt;!-- Add the Plans code block here --&gt;
 
&lt;/VerticalStackLayout&gt;
</code></pre><h2 id="benefits--plans">4. Benefits &amp; Plans</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/05_benefits_and_plans.png?sfvrsn=897d8827_2" title="Benefits and plans block" alt=".NET MAUI travel app benefits and plans" /></p><p>For this block, we&rsquo;ll also use Telerik RadBorder, so make sure to include the same namespace used on the previous page here as well. This section is composed of the following elements:</p><p>➖ <strong>Benefits:</strong> We&rsquo;ll use a CollectionView so the information can be loaded from a flexible list, instead of adding each item manually in XAML. Each item will include a checkmark image and a label with the benefit name.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;CollectionView.ItemTemplate&gt; 
&lt;DataTemplate&gt; 
    &lt;HorizontalStackLayout Spacing="10" Padding="0,8"&gt; 
    &lt;Image Source="check" HeightRequest="20" WidthRequest="20"/&gt; 
    &lt;Label Text="{Binding Description}" FontSize="12"/&gt; 
    &lt;/HorizontalStackLayout&gt; 
    &lt;/DataTemplate&gt; 
&lt;/CollectionView.ItemTemplate&gt; 
&lt;/CollectionView
</code></pre><p>➖<strong>Plans:</strong> We&rsquo;ll also use a CollectionView for the plan selector. Each item will be displayed inside a box with rounded blue borders and will contain the plan name, the discount, the current price and the previous price.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;CollectionView VerticalScrollBarVisibility="Never" 
ItemsSource="{Binding plans}"&gt; 
    &lt;CollectionView.ItemTemplate&gt; 
    &lt;DataTemplate&gt; 
    &lt;telerik:RadBorder Grid.Row="1" 
    BorderColor="#b9d7e1" 
    BorderThickness="2" 
    CornerRadius="20" 
    Margin="0,10,0,0" 
    Padding="10,15"&gt; 
    &lt;Grid ColumnDefinitions="auto,auto,*,auto" VerticalOptions="Center"&gt; 
    &lt;Label Grid.Column="0" Text="{Binding Name}" FontSize="14" FontAttributes="Bold" VerticalTextAlignment="Center" /&gt;
     
    &lt;telerik:RadBorder Grid.Column="1" 
    BackgroundColor="#F2555A" 
    BorderThickness="2" 
    CornerRadius="50" 
    Padding="10,6"&gt;
    
    &lt;Label 
    Text="{Binding Discount}" 
    TextColor="White" 
    FontAttributes="Bold" 
    FontSize="12" 
    HorizontalTextAlignment="Center" 
    VerticalTextAlignment="Center" /&gt; 
    &lt;/telerik:RadBorder&gt;
     
    &lt;Label Grid.Column="2" Text="{Binding Price} " FontSize="14" VerticalTextAlignment="Center" HorizontalTextAlignment="End" FontAttributes="Bold"/&gt;
    
    &lt;Label Grid.Column="3" Text="{Binding OldPrice}" VerticalTextAlignment="Center" TextDecorations="Strikethrough" FontSize="14" TextColor="Gray"/&gt; 
    &lt;/Grid&gt; 
    &lt;/telerik:RadBorder&gt; 
    &lt;/DataTemplate&gt; 
    &lt;/CollectionView.ItemTemplate&gt; 
&lt;/CollectionView&gt;
</code></pre><h2 id="footer">5. Footer</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/06_footer.png?sfvrsn=c66819db_2" title="Footer block" alt=".NET MAUI travel app footer" /></p><p>Oh yeah! We&rsquo;ve reached the final block, the footer. This section includes a centered label and a button (using Telerik RadButton). To add it, go to the main Grid of this screen and locate the comment <code>&lt;!-- Add the footer code here --&gt;</code>.</p><p>Then, place the following code in that section:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Grid.Row="1" Text="Can be cancelled at any time" FontSize="13" TextColor="Grey" VerticalOptions="End" HorizontalTextAlignment="Center"/&gt;

&lt;telerik:RadButton Grid.Row="2" Text="Become Member" BackgroundColor="#0c538f" CornerRadius="10" VerticalOptions="End"/&gt;
</code></pre><p>And that&rsquo;s it&mdash;we&rsquo;re all done!  Below, you can see the final result of both screens.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/07_final_results.png?sfvrsn=ed18f275_2" title="Final results" alt=".NET MAUI travel app final result" /></p><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, we explored how to build a travel UI using .NET MAUI with XAML, inspired by a modern design.</p><p>I hope this guide helps you take these ideas and practices and apply them to your own UI implementations, especially when working with layouts, overlapping elements, and Telerik components.</p><p>If you have any questions or would like me to dive deeper into a specific part, feel free to leave a comment, I&rsquo;ll be happy to help! </p><p>See you in the next article! &zwj;♀️</p><p>Remember, Telerik UI for .NET MAUI comes with a free 30-day trial. See what you can create:</p><p><a target="_blank" href="https://www.telerik.com/try/ui-for-maui" class="Btn">Try Now</a></p><img src="https://feeds.telerik.com/link/23059/17371196.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:80b15211-473c-45fd-8937-2de83c237f13</id>
    <title type="text">Replicating a Ticket Screen in .NET MAUI</title>
    <summary type="text">Travel! It’s one of our favorite things, and here is how to build a flight ticket screen in .NET MAUI.</summary>
    <published>2026-06-22T17:00:48Z</published>
    <updated>2026-07-12T06:22:21Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17365403/replicating-ticket-screen-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Travel! It&rsquo;s one of our favorite things, and here is how to build a flight ticket screen in .NET MAUI.</span></p><p>I dare to say that one of the most loved hobbies, and one of the reasons we want vacations to arrive quickly, is traveling.  Guilty as charged, haha.</p><p>But personally, beyond the trip itself, I really enjoy being involved in the whole experience&mdash;from packing my bags to having my flight ticket in an app. But you know what&rsquo;s the most fun part? Besides having my ticket in an app, I can also combine my passion for traveling with my profession, by programming and replicating an app that brings these two things together.</p><p>For this reason, in this article you will continue strengthening your UI skills in .NET MAUI. Get it out of your head that you can&rsquo;t build beautiful and creative UIs, because you absolutely can.  Today we will replicate a ticket UI inspired by a <a target="_blank" href="https://dribbble.com/shots/17661430-Ticket-App-Mobile-application-concept">Dribbble</a> design, which will allow us to practice using several .NET MAUI components such as <strong>Shapes, Grid, Label</strong>, and especially a super special component: the <a target="_blank" href="https://www.telerik.com/maui-ui/border">.NET MAUI Border</a> from Progress Telerik UI. All of this in a very simple way. We&rsquo;ll break it down step by step!</p><p><strong>How will the explanation work?</strong></p><p>So you can understand everything 100%, I&rsquo;ll explain how the process will work:</p><p>➖<strong>Visual diagram:</strong> Before we start, you&rsquo;ll see a diagram with a screenshot of the design we want to achieve. This design will be divided into blocks, each identified with a name and a color. Each block will be explained individually.</p><p>➖<strong>Code explanation per block:</strong> In addition to the text explanation, each block will include the exact code snippet you need to write to achieve the result.</p><p>➖<strong>Step-by-step visual progress:</strong> Each explanation will have its corresponding screenshot, so you can see the progress as we build the UI.</p><p>⚠️ For the purposes of these articles, there will be some changes to the original user interface.</p><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-06/00_visual_structure.png?sfvrsn=a4b7e5c4_2" title="Visual structure" alt="Visual structure of ticket app. Main border, passenger info, perforated edges" /></p><h2 id="main-border-block">1. Main Border Block</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/01_first_block_design.png?sfvrsn=3bc792c5_2" title="First block design" alt="First block design - blue background" /></p><p>Let&rsquo;s start building the first block. This block is the most important one, since it contains all the elements of the remaining blocks.</p><p>To replicate the element in this block, we need a control that allows us to add a background color and apply rounded corners.</p><p>We will use the <a target="_blank" href="https://www.telerik.com/maui-ui/border">RadBorder</a> control from Progress Telerik. This control makes it easy to manage border color, thickness and even apply different corner radius values for each side. It&rsquo;s super useful!</p><p><strong>To use it, keep the following in mind:</strong></p><ol><li><p><strong>If you don&rsquo;t have a Telerik account yet, you can create one <a target="_blank" href="https://www.telerik.com/account/">for free</a></strong>. You&rsquo;ll get access to a trial license so you can explore not only RadBorder, but all the Telerik UI for .NET MAUI controls.</p></li><li><p><strong>You need to install Telerik UI for .NET MAUI.</strong> This is a one-time setup, meaning you don&rsquo;t need to do it for every component you use. (If you don&rsquo;t have it installed yet, I&rsquo;ve included an article where it is explained step by step how to set it up in both <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/first-steps-vs">Visual Studio</a> and <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/first-steps-vs-code">Visual Studio Code</a>).</p></li></ol><p>Once you have these two points ready, go to your XAML and follow these steps:</p><ol><li>Add the following namespace:</li></ol><pre class=" language-xml"><code class="prism  language-xml">xmlns:telerik="clr-namespace:Telerik.Maui.Controls;assembly=Telerik.Maui.Controls"
</code></pre><ol start="2"><li>Add a RadBorder to serve as the main container. Configure it with a background color of #29b7fc, a CornerRadius of 30, and apply Padding and Margin to control internal and external spacing, respectively.</li></ol><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadBorder VerticalOptions="Fill" 
    BackgroundColor="#29b7fc" 
    CornerRadius="30" 
    Padding="30" 
    Margin="20"&gt; 
    
&lt;!-- Please add the code for the following block here. --&gt;     

&lt;/telerik:RadBorder&gt;
</code></pre><h2 id="passenger-information-block">2. Passenger Information Block</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/02_second_block_design.png?sfvrsn=8856c19b_2" title="Second block design" alt="Second block design: passenger info" /></p><p>This second block contains approximately 95% of the remaining UI design. This is where we will display the ticket details, such as the airline name, origin and destination (from, to), gate and the customer&rsquo;s name.</p><p>We will start by adding a Grid. This will allow us, in the next block, to apply the rounded side cut effect that makes the design resemble a ticket.</p><p>⚠️ <strong>Note:</strong> This Grid must be added exactly on the line in the previous code block that says:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;!-- Please add the code for the following block here. --&gt;

&lt;Grid RowDefinitions="auto,auto" 
    ColumnDefinitions="*,*"&gt;" 
    &lt;!-- Add the border here --&gt; 
&lt;/Grid&gt;
</code></pre><p>Now, add a border with a white background. We will continue using the Telerik <strong>RadBorder</strong> control to maintain design consistency.</p><pre class=" language-xml"><code class="prism  language-xml">    &lt;telerik:RadBorder Grid.Row="0" Grid.Column="0" 
    Grid.ColumnSpan="2" 
    BackgroundColor="White" 
    VerticalOptions="Fill" 
    CornerRadius="30" 
    Padding="30"&gt; 

    &lt;!-- Add the Grid here --&gt; 
    
    &lt;/telerik:RadBorder&gt; 
    
    &lt;!-- Add the circles here --&gt;
</code></pre><p>Inside this RadBorder, we will add another Grid to organize all the ticket information.</p><p>This Grid will have three columns and fourteen rows, giving us the structure needed to properly arrange each element in the UI.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid ColumnDefinitions="*,auto,*" 
    RowDefinitions="auto,auto,auto,auto,auto,auto,auto,auto,auto,auto,auto,auto,auto,auto" 
    RowSpacing="20"&gt;
 
    &lt;!--Add all the information here -- &gt; 

&lt;/Grid&gt;
</code></pre><p>Finally, let&rsquo;s add all the passenger information. For the first section, we will use a HorizontalStackLayout, while the remaining structure will be built using Label elements, Line elements and a sample image to represent the barcode.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;HorizontalStackLayout Grid.Column="0" 
    Grid.ColumnSpan="3" Grid.Row="0" 
    Spacing="20" 
    VerticalOptions="Center"&gt; 
    &lt;Image Source="arrowlogo.png" 
    HeightRequest="40" 
    Aspect="AspectFill" 
    WidthRequest="40" /&gt; 
    &lt;Label Text="United Airlines" FontSize="15" FontAttributes="Bold" VerticalTextAlignment="Center"/&gt; 
&lt;/HorizontalStackLayout&gt;
 
&lt;Line Grid.Row="1" Stroke="LightGrey" StrokeThickness="0.6" X2="800" HorizontalOptions="Center"/&gt;
 
&lt;Image Grid.Row="2" Grid.Column="1" Source="airplane" HeightRequest="13" WidthRequest="13"/&gt; 

&lt;Label Grid.Row="2" Grid.Column="0" Text="From" FontSize="10" TextColor="Gray"/&gt;

&lt;Label Grid.Row="3" Grid.Column="0" Text="LAX" FontSize="16" FontAttributes="Bold" /&gt;

&lt;Label Grid.Row="4" Grid.Column="0" Text="Los Angeles, USA &amp;#10;5:05, Mon 16 Aug&amp;#10;Terminal 1" FontSize="10" TextColor="Gray" /&gt;

&lt;Label Grid.Row="2" Grid.Column="2" Text="NYC" HorizontalTextAlignment="End" FontSize="10" TextColor="Gray" /&gt;

&lt;Label Grid.Row="3" Grid.Column="2" Text="LAX" HorizontalTextAlignment="End" FontSize="16" FontAttributes="Bold"/&gt;

&lt;Label Grid.Row="4" Grid.Column="2" Text="New York, USA&amp;#10;10:55, Mon. 15 Aug&amp;#10;Terminal 1" HorizontalTextAlignment="End" FontSize="10" TextColor="Gray" /&gt;
 
&lt;Line Grid.Row="5" Stroke="LightGrey" StrokeThickness="0.6" X2="800" HorizontalOptions="Center"/&gt; 

&lt;Label Grid.Row="6" Grid.Column="0" Text="Gate" FontSize="10" TextColor="Gray" /&gt;

&lt;Label Grid.Row="7" Grid.Column="0" Text="C2" FontSize="15" FontAttributes="Bold"/&gt;
 
&lt;Label Grid.Row="6" Grid.Column="2" Text="Seat Place" FontSize="10" TextColor="Gray"/&gt;

&lt;Label Grid.Row="7" Grid.Column="2" Text="B2" FontSize="15" FontAttributes="Bold" /&gt;
 
&lt;Line Grid.Row="8" Stroke="LightGrey" StrokeThickness="0.6" X2="800" HorizontalOptions="Center" /&gt;
 
&lt;Label Grid.Row="9" Grid.Column="0" Text="Full Name" FontSize="10" TextColor="Gray" /&gt;

&lt;Label Grid.Row="10" Grid.Column="0" Text="Tom Smith" FontSize="15" FontAttributes="Bold"/&gt; 

&lt;Label Grid.Row="9" Grid.Column="2" Text="Class" FontSize="10" TextColor="Gray"/&gt;

&lt;Label Grid.Row="10" Grid.Column="2" Text="Economy" FontSize="15" FontAttributes="Bold" /&gt;
 
&lt;Line Grid.Row="11" Stroke="LightGrey" StrokeThickness="0.6" X2="800" HorizontalOptions="Center" /&gt; 

&lt;Label Grid.Row="12" Grid.Column="0" Text="Booking Code" FontSize="15" FontAttributes="Bold"/&gt;

&lt;Label Grid.Row="12" Grid.Column="2" Text="G1540D4" FontSize="15" FontAttributes="Bold" /&gt; 

&lt;Image Grid.Row="13" Grid.Column="0" Grid.ColumnSpan="3" Source="barcodesample" Aspect="Fill"/&gt;
</code></pre><h2 id="perforated-edges-block">3. Perforated Edges Block</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/03_third_block_design.png?sfvrsn=a6c89f1e_2" title="Third block design" alt="Third block design - perforated edges" /></p><p>Now, we are adding the finishing touch to this UI: simulating the ticket side cutouts on the white background Border. To achieve this, we will use the Ellipse shape from .NET MAUI.</p><p>We will add two Ellipse elements, one on each side, to recreate the visual effect of a ticket.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Ellipse Grid.Row="0" Grid.Column="0" 
    HeightRequest="60" 
    TranslationX="-130" 
    TranslationY="130" 
    Fill="#29b7fc"/&gt;
 
&lt;Ellipse Grid.Row="0" Grid.Column="1" 
    HeightRequest="60" 
    TranslationX="130" 
    TranslationY="130" 
    Fill="#29b7fc"/&gt;
</code></pre><p>⚠️ Please note: this code must be placed exactly in one of the sections of the second block where it says: <code>&lt;!-- Add the circles here --&gt;</code>.</p><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, we explored how to build a ticket screen using .NET MAUI with XAML, recreating a modern and visually appealing boarding pass design.</p><p>I hope this guide helps you understand how to approach similar UI challenges and inspires you to recreate more complex designs in your own .NET MAUI applications.</p><p>If you have any questions or would like me to explore a specific part in more detail, feel free to leave a comment&mdash;I&rsquo;ll be happy to help! </p><p>See you in the next article! &zwj;♀️</p><p>If you want to learn more about Ellipse in .NET MAUI, I invite you to read the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/user-interface/controls/shapes/ellipse?view=net-maui-10.0">Microsoft Learn article</a>. It is a very useful element for creating creative UI designs.</p><h3 id="additional-resources">Additional Resources</h3><p>I invite you to learn more about the Telerik RadBorder.</p><ul><li><a target="_blank" href="https://www.telerik.com/maui-ui/border">Here you can explore the main features and benefits of the product.</a></li><li><a target="_blank" href="https://www.telerik.com/maui-ui/documentation/controls/border/getting-started">Here you can review its technical implementation.</a></li><li>And, don&rsquo;t forget: You can <a target="_blank" href="https://www.telerik.com/try/ui-for-maui"><strong>try Telerik UI for .NET MAUI free for 30 days</strong></a>. </li></ul><img src="https://feeds.telerik.com/link/23059/17365403.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:edd3110a-7b4d-4f43-8db1-b9001b1e73be</id>
    <title type="text">Creating Localized .NET MAUI Applications</title>
    <summary type="text">Reach more people with your apps: Learn how to localize .NET MAUI applications, including XAML text elements, view models and prebuilt Telerik controls for .NET MAUI.</summary>
    <published>2026-06-17T20:17:33Z</published>
    <updated>2026-07-12T06:22:21Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17362859/creating-localized-net-maui-applications"/>
    <content type="text"><![CDATA[<p><span class="featured">Reach more people with your apps: Learn how to localize .NET MAUI applications, including XAML text elements, view models and prebuilt Telerik controls for .NET MAUI.</span></p><p>Making our mobile applications accessible to users who speak a different language than us can make a huge difference in their usage. Fortunately, .NET MAUI offers the power to deliver multi-language applications thanks to the use of resources files.</p><p>Likewise, prebuilt controls such as those from Progress <a href="https://www.telerik.com/maui-ui">Telerik UI for .NET MAUI</a> can be adapted to support localization, allowing you to build and deliver native language experiences quickly. Let&rsquo;s see how to do it!</p><h2 id="understanding-localization-in-.net-maui-apps">Understanding Localization in .NET MAUI Apps</h2><p>Localization is the process of enabling an application to support different languages and cultures; that is, it&rsquo;s not only about translating text strings to other languages, but also adapting date formats, numbers, etc.</p><p>There are some key elements for localizing applications, the first of which are the resource files <strong>.resx</strong>, which are XML files composed of key-value pairs for each language.</p><p>Likewise, we have the class <code>CultureInfo</code>, which represents the user&rsquo;s cultural information. Finally, the class <code>ResourceManager</code> is a class that allows us at runtime to retrieve localized strings according to the language selected on the user&rsquo;s device.</p><h2 id="creating-a-sample-app-to-localize">Creating a Sample App to Localize</h2><p>To show you in a practical way how to integrate localization into your own projects, let&rsquo;s create a test project. To do so, create a new .NET MAUI project without example content, and follow the <a href="https://www.telerik.com/maui-ui/documentation/get-started/first-steps-vs#step-1-set-up-your-net-maui-application">installation guide to add Telerik controls for .NET MAUI</a> to the project.</p><p>Also install the NuGet package <code>CommunityToolkit.Mvvm</code> to create viewmodels cleanly. Once the project has been configured, create a data model to represent a <code>Product</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">Product</span>
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <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">public</span> <span class="token keyword">string</span> Category <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <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">public</span> <span class="token keyword">decimal</span> Price <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> DateTime CreatedDate <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>Next, let&rsquo;s create a viewmodel that will display information in the UI for a set of fictitious products:</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">MainViewModel</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>Product<span class="token operator">&gt;</span> products <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>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">private</span> DateTime<span class="token operator">?</span> selectedDate<span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token function">MainViewModel</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        SelectedDate <span class="token operator">=</span> DateTime<span class="token punctuation">.</span>Now<span class="token punctuation">;</span>
        <span class="token function">LoadProducts</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">void</span> <span class="token function">LoadProducts</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        Products <span class="token operator">=</span>
        <span class="token punctuation">[</span>
            <span class="token keyword">new</span> <span class="token class-name">Product</span>
            <span class="token punctuation">{</span>
                Name <span class="token operator">=</span> <span class="token string">"Laptop Pro 15"</span><span class="token punctuation">,</span>
                Category <span class="token operator">=</span> <span class="token string">"Electronics"</span><span class="token punctuation">,</span>
                Price <span class="token operator">=</span> <span class="token number">1299</span><span class="token punctuation">.</span>99m<span class="token punctuation">,</span>
                CreatedDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2026</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">15</span><span class="token punctuation">)</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token keyword">new</span> <span class="token class-name">Product</span>
            <span class="token punctuation">{</span>
                Name <span class="token operator">=</span> <span class="token string">"Running Shoes"</span><span class="token punctuation">,</span>
                Category <span class="token operator">=</span> <span class="token string">"Clothing"</span><span class="token punctuation">,</span>
                Price <span class="token operator">=</span> <span class="token number">89</span><span class="token punctuation">.</span>95m<span class="token punctuation">,</span>
                CreatedDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2026</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">)</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token keyword">new</span> <span class="token class-name">Product</span>
            <span class="token punctuation">{</span>
                Name <span class="token operator">=</span> <span class="token string">"Organic Coffee Beans"</span><span class="token punctuation">,</span>
                Category <span class="token operator">=</span> <span class="token string">"Food"</span><span class="token punctuation">,</span>
                Price <span class="token operator">=</span> <span class="token number">24</span><span class="token punctuation">.</span>50m<span class="token punctuation">,</span>
                CreatedDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2026</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token keyword">new</span> <span class="token class-name">Product</span>
            <span class="token punctuation">{</span>
                Name <span class="token operator">=</span> <span class="token string">"Wireless Mouse"</span><span class="token punctuation">,</span>
                Category <span class="token operator">=</span> <span class="token string">"Electronics"</span><span class="token punctuation">,</span>
                Price <span class="token operator">=</span> <span class="token number">45</span><span class="token punctuation">.</span>00m<span class="token punctuation">,</span>
                CreatedDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2025</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token keyword">new</span> <span class="token class-name">Product</span>
            <span class="token punctuation">{</span>
                Name <span class="token operator">=</span> <span class="token string">"Winter Jacket"</span><span class="token punctuation">,</span>
                Category <span class="token operator">=</span> <span class="token string">"Clothing"</span><span class="token punctuation">,</span>
                Price <span class="token operator">=</span> <span class="token number">159</span><span class="token punctuation">.</span>99m<span class="token punctuation">,</span>
                CreatedDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2026</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">28</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 code above, you can notice that hard-coded strings in English are used to display information to users only in that language. Now, let&rsquo;s create an example UI, using a <a href="https://www.telerik.com/maui-ui/datepicker">.NET MAUI RadDatePicker</a> (which is an enhanced DatePicker) and a <a href="https://www.telerik.com/maui-ui/datagrid">MAUI RadDataGrid</a> to easily display data tables:</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>16<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 attr-name">RowSpacing</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;!--  Welcome message  --&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>20<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>Welcome to the app<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
 <span class="token comment">&lt;!--  Date picker  --&gt;</span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>HorizontalStackLayout</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">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>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">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>Created Date<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>RadDatePicker</span>
         <span class="token attr-name">Date</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SelectedDate}<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>250<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 comment">&lt;!--  Product grid  --&gt;</span>
 <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadDataGrid</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">AutoGenerateColumns</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">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">UserFilterMode</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">UserGroupMode</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">UserSortMode</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><span class="token namespace">telerik:</span>RadDataGrid.Columns</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>DataGridTextColumn</span> <span class="token attr-name">HeaderText</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Product Name<span class="token punctuation">"</span></span> <span class="token attr-name">PropertyName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Name<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>DataGridTextColumn</span> <span class="token attr-name">HeaderText</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Category<span class="token punctuation">"</span></span> <span class="token attr-name">PropertyName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Category<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>DataGridNumericalColumn</span>
             <span class="token attr-name">CellContentFormat</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{}{0:C}<span class="token punctuation">"</span></span>
             <span class="token attr-name">HeaderText</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Price<span class="token punctuation">"</span></span>
             <span class="token attr-name">PropertyName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Price<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>DataGridDateColumn</span>
             <span class="token attr-name">CellContentFormat</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{}{0:d}<span class="token punctuation">"</span></span>
             <span class="token attr-name">HeaderText</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Created Date<span class="token punctuation">"</span></span>
             <span class="token attr-name">PropertyName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>CreatedDate<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>RadDataGrid.Columns</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>RadDataGrid</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>Don&rsquo;t forget to register both <code>MainPage</code> and <code>MainPageViewModel</code> in the dependency container:</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>MainPage<span class="token punctuation">&gt;</span></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>MainViewModel<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>Finally, let&rsquo;s inject the view model into the page&rsquo;s code-behind, while assigning the injected reference to <code>BindingContext</code>:</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">MainPage</span> <span class="token punctuation">:</span> ContentPage
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token function">MainPage</span><span class="token punctuation">(</span>MainViewModel 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>
<span class="token punctuation">}</span>
</code></pre><p>After implementing the above changes, we will have a UI like the following:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/base-app-product-grid-english.png?sfvrsn=287ffbd9_2" alt="Product grid in base app with English labels" /></p><p>As we anticipated, all the UI content is in English. Some text chunks we might want to internationalize could be the page title, the welcome message, column headers, product categories, etc. Let&rsquo;s see how to achieve it.</p><h2 id="creating-resource-files-to-localize-a-.net-maui-app">Creating Resource Files to Localize a .NET MAUI App</h2><p>Localization of .NET applications is based on resource files. To create these files, you must start by creating a file with the extension <code>.resx</code>, which will contain the strings in the original language.</p><p>In our example, we are going to create a new folder <code>Resources/Strings</code>, and inside create a file named <code>AppStrings.resx</code>. You can achieve this using the context menu on the created folder, selecting <strong>Add</strong> | <strong>New Item</strong>. Then, in the search box enter the term <strong>resources</strong>, which will filter the template for the resource file:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/selecting-resource-template.png?sfvrsn=943723e7_2" alt="Selecting the appropriate template for a resource file" /></p><p>Once you have created the file, you can open it and start adding the application&rsquo;s strings in their original language, using the <strong>+</strong> button. This will open a new window where you can enter information such as the string key, the data type, the value and optionally comments:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/adding-localization-string.png?sfvrsn=68f8fbaf_2" alt="Developer adding a new localization string in editor" /></p><p>Another way to add strings more quickly is to paste them in the format: <strong>Key name</strong> + <strong>tab</strong> + <strong>value</strong>. For example, you can copy and paste the following content, and paste it directly into the resource editor, which will create a series of rows in the file:</p><pre class=" language-text"><code class="prism  language-text">LanguageLabelLanguage
ProductNameProduct Name
CategoryCategory
PricePrice
CreatedDateCreated Date
SelectLanguageSelect a language
ElectronicsElectronics
ClothingClothing
FoodFood
FilterProductsFilter Products
WelcomeWelcome to the localized app
</code></pre><p>After having the base file, the next step is to create an additional resource file for each translation you want to perform. For the example, I will create a new file in <code>Resources/Strings</code> called <code>AppStrings.es.resx</code>. You can notice that each new file must be named the same as the main one, adding the ISO code of the language you want to translate to.</p><p>When you open the file, you will see that a new column has been added, where you can enter the information of the file, as in the following example:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/resx-translation-strings.png?sfvrsn=9ced7f57_2" alt="Resx files showing original and translated string values" /></p><p>With the resource files created, it is time to connect the strings with the UI.</p><h2 id="localizing-elements-in-the-ui">Localizing Elements in the UI</h2><p>With the strings correctly localized, let&rsquo;s go to the UI page. There, you need to add a namespace for the path where the localized files are located, similar to this:</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>resx</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>clr-namespace:MauiLocalizedApps.Resources.Strings<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
</code></pre><p>Then, on each element you want to localize you must use the markup extension <code>x:Static</code>, using the key of the resource you want to replace. This is an example of the Label control corresponding to the localized welcome message:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>
<span class="token attr-name">...</span>
    <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{x:Static resx:AppStrings.Welcome}<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
</code></pre><p>Other strings we will replace will be the creation date and the welcome one, as shown 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>ContentPage</span> <span class="token attr-name">...</span>
    <span class="token attr-name">Title</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{x:Static resx:AppStrings.AppTitle}<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">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 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 attr-name">RowSpacing</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;!--  Welcome message  --&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>20<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>{x:Static resx:AppStrings.Welcome}<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
     <span class="token comment">&lt;!--  Date picker  --&gt;</span>
     <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>HorizontalStackLayout</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">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>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">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>{x:Static resx:AppStrings.CreatedDate}<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>RadDatePicker</span> <span class="token attr-name">Date</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SelectedDate}<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>250<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>Grid</span><span class="token punctuation">&gt;</span></span>     
</code></pre><p>After applying the changes and changing the device language to Spanish, we get the following result:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/xaml-spanish-localized-strings.png?sfvrsn=7b00648d_2" alt="Screenshot of XAML file with Spanish localized strings" /></p><p>Now, let&rsquo;s see how to localize the view model strings.</p><h2 id="localizing-data-strings-from-the-viewmodel">Localizing Data Strings from the viewmodel</h2><p>In addition to localizing elements in the XAML file, we can also load translated strings that are found in the view model. For example, suppose we want to translate the names of the categories shown in the DataGrid.</p><p>To achieve this, we can use the static class that is created when we create a resource file, which takes the same name as the created file. In our case it is called <code>AppStrings</code>, and we will use it as follows:</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">LoadProducts</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    Products <span class="token operator">=</span>
    <span class="token punctuation">[</span>
        <span class="token keyword">new</span> <span class="token class-name">Product</span>
        <span class="token punctuation">{</span>
            <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
            Category <span class="token operator">=</span> AppStrings<span class="token punctuation">.</span>Electronics
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token keyword">new</span> <span class="token class-name">Product</span>
        <span class="token punctuation">{</span>
            <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
            Category <span class="token operator">=</span> AppStrings<span class="token punctuation">.</span>Clothing<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>With the previous changes, we have seen how to display translated strings to the user found in XAML files and view models:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/localized-viewmodel-text.png?sfvrsn=f3f493dc_2" alt="Localized text rendered from view models in interface" /></p><p>However, we still have strings in the graphical controls that have not been localized. Let&rsquo;s see how to translate them.</p><h2 id="localizing-internal-strings-of-telerik-controls-for-.net-maui">Localizing Internal Strings of Telerik Controls for .NET MAUI</h2><p>In case you also want to localize the strings of Telerik controls, such as those that show options in the DataGrid, you can see all the keys used in the controls on the <a href="https://www.telerik.com/maui-ui/documentation/globalization-localization">.NET MAUI globalization and localization</a> page. On that page you will find links for each control and their respective strings.</p><p>For example, to localize the .NET MAUI DataGrid, we must copy a series of keys that start with <code>DataGrid_...</code>, such as <code>DataGrid_DistinctValues_SelectAll</code>, <code>DataGrid_Filter_ApplyFilter</code>, <code>DataGrid_Filter_ResetFilter</code>, etc. These are the keys that I will add to the file <code>AppStrings.resx</code>.</p><p>After doing this, you must create a class that inherits from <code>TelerikLocalizationManager</code>, like the one shown below:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">internal</span> <span class="token keyword">class</span> <span class="token class-name">CustomLocalizationManager</span> <span class="token punctuation">:</span> TelerikLocalizationManager
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token keyword">string</span> <span class="token function">GetString</span><span class="token punctuation">(</span><span class="token keyword">string</span> key<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">string</span><span class="token operator">?</span> localizedValue <span class="token operator">=</span> AppStrings<span class="token punctuation">.</span>ResourceManager<span class="token punctuation">.</span><span class="token function">GetString</span><span class="token punctuation">(</span>
            key<span class="token punctuation">,</span> CultureInfo<span class="token punctuation">.</span>CurrentUICulture<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><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>localizedValue<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">return</span> localizedValue<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">return</span> <span class="token keyword">base</span><span class="token punctuation">.</span><span class="token function">GetString</span><span class="token punctuation">(</span>key<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 use the <code>GetString</code> method to attempt to retrieve a key and its translated value in the device&rsquo;s language. If a translated string is found it is returned; otherwise the original value is returned.</p><p>Finally, you must register the created manager in <code>MauiProgram.cs</code> as follows:</p><pre class=" language-csharp"><code class="prism  language-csharp"><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>
    TelerikLocalizationManager<span class="token punctuation">.</span>Manager <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CustomLocalizationManager</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>
</code></pre><p>When running the app, we will get the following result:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-06/telerik-datagrid-spanish-strings.gif?sfvrsn=cd4718ff_2" alt="Telerik DataGrid displaying Spanish localization strings" /></p><p>In the image above you can see how the DataGrid options are displayed translated into Spanish. With this, we have finished localizing the strings in our application.</p><h2 id="conclusion">Conclusion</h2><p>Throughout this article you&rsquo;ve seen how to localize .NET MAUI applications. You&rsquo;ve seen how to translate text elements found in XAML files, view models and even prebuilt Telerik controls for .NET MAUI. Now it&rsquo;s your time to reach more people with your apps by using localization through resource files.</p><blockquote><p>Try out Telerik UI for .NET MAUI free for 30 days.</p><p>&nbsp;</p><p><a target="_blank" href="https://www.telerik.com/try/ui-for-maui" class="Btn">Try Now</a></p></blockquote><img src="https://feeds.telerik.com/link/23059/17362859.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:95c1b59f-0f37-46a9-a08b-2560c179c4bf</id>
    <title type="text">Getting Contact Information with .NET MAUI</title>
    <summary type="text">Let users easily pull contact info (like name, number, email) from one app and save it to their device’s contact list in .NET MAUI.</summary>
    <published>2026-06-08T17:06:18Z</published>
    <updated>2026-07-12T06:22:21Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17356406/getting-contact-information-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Let users easily pull contact info (like name, number, email) from one app and save it to their device&rsquo;s contact list in .NET MAUI.</span></p><p>Let&rsquo;s be honest, the only &ldquo;accessory&rdquo; you take with you everywhere&mdash;no matter the activity you&rsquo;re doing or the type of event it is, and something that never bothers you to carry&mdash;is your mobile device. </p><p>OK &hellip; and what does this mean? It means that a large part of the things you need to do in your day-to-day life are covered by your phone: from super basic operations like calculating amounts and saving contacts, to talking with your friends or even ordering food.</p><p>Now, think about this: imagine you have an application with a form where you need to enter contact information&mdash;the same information you already saved on your phone when creating that contact. Having to type everything again can feel tedious, right?</p><p>This is where things get interesting. A simple action like saving a contact opens the door for multiple applications to obtain that information and work together with the data that already exists on the device. If your app could &ldquo;pull&rdquo; that information directly, without the user having to type it again, that would be a win! </p><p>So get excited, because in this article I&rsquo;ll show you how to obtain that contact information to use it in your .NET MAUI apps. </p><h2 id="what-do-i-need-before-i-start">What Do I Need Before I Start?</h2><p>Before we begin, it&rsquo;s important to configure a few platform-specific steps. Let&rsquo;s go through each one, step by step:</p><h3 id="android">Android</h3><p>To be able to read contacts, you must explicitly request the <code>READ_CONTACTS</code> permission. There are three different ways to add this permission on Android:</p><p><strong>Option 1: Add the permission directly in the AndroidManifest.xml</strong></p><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.READ_CONTACTS" /&gt;
</code></pre><p><strong>Option 2: Use the Android Manifest graphical editor</strong></p><p>Go to <strong>Platforms &rarr; Android,</strong> double-click the <strong>AndroidManifest.xml</strong> file, and locate the <strong>Required permissions</strong> section. Find the permission labeled <strong>READ_CONTACTS</strong> and simply check the option, as shown below.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/01_readcontacts.png?sfvrsn=6ec6edc6_2" title="Read Contacts Permissions" alt="" /></p><p><strong>Option 3: Add the assembly-based permission</strong></p><p>Go to <strong>Platforms &rarr; Android &rarr; MainApplication.cs</strong> and add the permission as follows:</p><pre class=" language-csharp"><code class="prism  language-csharp">[assembly: UsesPermission(Android.Manifest.Permission.ReadContacts)]
</code></pre><h3 id="iosmac-catalyst">iOS/Mac Catalyst</h3><p>On <strong>iOS</strong> and <strong>Mac Catalyst</strong>, we also need a very similar configuration to be able to access contacts. Follow these steps:</p><p><strong>Step 1:</strong><br />Right-click on <strong>Platforms &rarr; iOS &rarr; Info.plist</strong> and on <strong>Platforms &rarr; MacCatalyst &rarr; Info.plist</strong> (yes, each configuration is done per platform) and open the file with the editor.</p><p><strong>Step 2:</strong><br />Once the file is open, add the <strong>NSContactsUsageDescription</strong> key along with its description. This step is mandatory to comply with Apple&rsquo;s guidelines. Keep in mind that this text must be very precise, as it will be the message shown to the user when the app requests permission to access their contacts.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;key&gt;NSContactsUsageDescription&lt;/key&gt;
&lt;string&gt;This app needs access to your contacts to select a contact and retrieve its information.&lt;/string&gt;
</code></pre><h3 id="windows">Windows</h3><p>Contact picking is not supported on Windows.</p><h2 id="let’s-start">Let&rsquo;s Start!</h2><p>All set! We&rsquo;ve prepared the initial configuration to get started! </p><p>.NET MAUI provides the IContacts interface, which allows us to select and retrieve information from the contacts stored on the device.</p><p>This interface is part of the Microsoft.Maui.ApplicationModel.Communication namespace and is available through the Default property, which gives us access to the ready-to-use implementation provided by .NET MAUI.</p><h3 id="important-considerations-for-ios-and-macos">Important Considerations for iOS and macOS</h3><p>There is a namespace conflict because multiple classes named Contacts exist. As a result, if you write only <code>Contacts</code>, .NET doesn&rsquo;t know exactly which one you are referring to, and you might think there is an issue with your code when in reality you are just using the wrong class.</p><p><strong>What&rsquo;s the Solution?</strong></p><p>To avoid this conflict, you must tell .NET exactly where the class you want to use comes from. This is done by using the fully qualified name:</p><pre class=" language-csharp"><code class="prism  language-csharp">Microsoft.Maui.ApplicationModel.Communication.Contacts
</code></pre><p><strong>A Cleaner Solution</strong></p><p>There is also a cleaner way to handle this. Instead of writing the full name every time you use it, you can create an alias with a using directive, like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">using Communication = Microsoft.Maui.ApplicationModel.Communication;
</code></pre><p>This gives the namespace a shorter name. Then, you can use that alias directly in your code:</p><pre class=" language-csharp"><code class="prism  language-csharp">var contact = await Communication.Contacts.Default.PickContactAsync();
</code></pre><h2 id="what-contact-information-can-we-retrieve-exactly">What Contact Information Can We Retrieve Exactly?</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/02_contact.png?sfvrsn=23e5e456_2" title="Contacts" alt="" /></p><p>Let&rsquo;s take a look at the data that can be retrieved from a contact. The following are the available fields:</p><ul><li><strong>Id:</strong> The internal identifier of the contact on the device.</li><li><strong>NamePrefix:</strong> The name prefix (Mr., Mrs., Eng., Dr., etc.)</li><li><strong>GivenName:</strong> The contact&rsquo;s first name.</li><li><strong>MiddleName:</strong> The contact&rsquo;s middle name.</li><li><strong>FamilyName:</strong> The contact&rsquo;s last name.</li><li><strong>NameSuffix:</strong> The name suffix (if any), for example, Jr.</li><li><strong>Phones:</strong> The list of phone numbers associated with the contact.</li><li><strong>Emails:</strong> The list of email addresses associated with the contact.</li><li><strong>DisplayName:</strong> The full name displayed on the phone. For example: Eng. Maris Lopez.</li></ul><h2 id="getting-your-device-contact-list">Getting Your Device Contact List</h2><p>To retrieve the full list of contacts stored on your device, you can use the <code>GetAllAsync()</code> method. This method returns a collection containing all available contacts.</p><p>Below is an example showing how to retrieve them:</p><pre class=" language-csharp"><code class="prism  language-csharp">public async IAsyncEnumerable&lt;string&gt; GetContactNames() 
{ 
    var contacts = await Contacts.Default.GetAllAsync(); 
// No contacts 
if (contacts == null) 
    yield break;
 
foreach (var contact in contacts) 
    yield return contact.DisplayName; 
}
</code></pre><h3 id="but-how-can-i-select-a-specific-contact-">But How Can I Select a Specific Contact? </h3><p>To ask the user to select a specific contact from their device, we use the <code>PickContactAsync()</code> method. This method opens the system&rsquo;s contact list, where the user can simply choose a contact.</p><blockquote><p>⚠️ If the user does not select any contact or cancels the action, the method returns null.</p></blockquote><p>In the following example, you can see how to retrieve the different pieces of information from the selected contact:</p><pre class=" language-csharp"><code class="prism  language-csharp">private async void SelectContactButton_Clicked(object sender, EventArgs e) 
{ 
    try 
    { 
    var contact = await Contacts.Default.PickContactAsync(); 
    
    if (contact == null) 
    return; 
    string id = contact.Id; 
    string namePrefix = contact.NamePrefix; 
    string givenName = contact.GivenName; 
    string middleName = contact.MiddleName; 
    string familyName = contact.FamilyName; 
    string nameSuffix = contact.NameSuffix; 
    string displayName = contact.DisplayName; 
    List&lt;ContactPhone&gt; phones = contact.Phones; 
    List&lt;ContactEmail&gt; emails = contact.Emails; 
    }
    
    catch (Exception ex) 
    { 
    // Most likely permission denied 
    } 
}
</code></pre><h2 id="✍️-platform-differences-you-should-know">✍️ Platform Differences You Should Know</h2><h3 id="android-1">Android</h3><ul><li><code>GetAllAsync</code> does not support the <code>cancellationToken</code> parameter.</li></ul><h3 id="ios--mac-catalyst">iOS / Mac Catalyst</h3><ul><li><code>GetAllAsync</code> does not support the <code>cancellationToken</code> parameter.</li><li>The <code>DisplayName</code> property is not supported natively. Instead, its value is constructed using <code>GivenName FamilyName</code>.</li></ul><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, you learned how to work with device contacts in .NET MAUI, from selecting a specific contact to retrieving the full contact list. You also explored key platform differences and important considerations to keep in mind when targeting Windows, Android, iOS and Mac Catalyst.</p><p>With this knowledge, you can now integrate contact access into your apps in a clear and reliable way, improving the user experience while handling platform-specific behaviors correctly.</p><p>See you in the next article! &zwj;♀️✨</p><h3 id="reference">Reference</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/contacts?view=net-maui-10.0&amp;tabs=macios">https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/communication/contacts?view=net-maui-10.0&amp;tabs=macios</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">Share Functionality in Your .NET MAUI Apps</h4></div><div class="col-8"><p class="u-fs16 u-mb0"><a target="_blank" href="https://www.telerik.com https://www.telerik.com/blogs/share-functionality-net-maui-apps">Learn how to add share functionality to your .NET MAUI app</a> whether in iOS, Android or Windows.</p></div></div></aside><img src="https://feeds.telerik.com/link/23059/17356406.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:862be530-d5bf-4f83-a53d-21c09f5f4a84</id>
    <title type="text">5 Heart Animations Using .NET MAUI</title>
    <summary type="text">Try your hand at some simple, engaging animations in .NET MAUI. Here are five heart animations you can master today!</summary>
    <published>2026-06-02T16:28:18Z</published>
    <updated>2026-07-12T06:22:21Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17352785/5-heart-animations-using-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Try your hand at some simple, engaging animations in .NET MAUI. Here are five heart animations you can master today!</span></p><p>I&rsquo;m a big fan of animations that capture the user&rsquo;s attention&mdash;the kind that don&rsquo;t just make an app look pretty, but also have the ability to guide users and clearly communicate what&rsquo;s happening. When used correctly, animations become a key part of design and usability. ✨</p><p>In .NET MAUI, we have simple yet very powerful animations that allow us to add that dynamic touch without unnecessary complexity. With just a few lines of code, we can transform common interactions into more natural and enjoyable experiences.</p><p>I genuinely love this article, because in it we&rsquo;ll learn how to create five super-creative animations that elevate our application and showcase the beautiful and powerful things we can achieve using the basic animations available in .NET MAUI </p><h2 id="heart-ecg-monitor">1. Heart ECG Monitor</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/01-heartecgmonitor.gif?sfvrsn=fd1f81d3_2" title="Heart ECG Monitor Demo" alt="Heart ECG Monitor Demo" /></p><p><strong>OMG, can we do this in .NET MAUI??</strong> Yess!!!  (This is my favorite animation, hahaha).</p><p>Let&rsquo;s create an ECG monitor&ndash;style animation, where we can see the movement of the line. To achieve this, we&rsquo;ll work with both XAML and code-behind.</p><p><strong>Let&rsquo;s start with the XAML. </strong></p><p>The design includes a heart and some lines that simulate the monitor&rsquo;s movement. Both elements will be vertically aligned, so the layout that will contain our design is a <strong>VerticalStackLayout.</strong></p><p>Inside this layout, we&rsquo;ll add:</p><p>➖ An Image for the heart<br />➖ And a GraphicsView to draw and animate the monitor lines</p><pre class=" language-xml"><code class="prism  language-xml">&lt;VerticalStackLayout Padding="24" Spacing="16"
   
    &lt;!-- Heart --&gt; 
    &lt;Image x:Name="Heart" 
    Source="redheart" 
    WidthRequest="35" 
    HeightRequest="35" 
    HorizontalOptions="Center" /&gt;
    
    &lt;!-- ECG --&gt; 
    &lt;GraphicsView x:Name="Ecg" 
    HeightRequest="120" /&gt;

&lt;/VerticalStackLayout&gt;
</code></pre><p>Perfect! Now we&rsquo;ll continue with the code that brings the monitor and the heart to life. For the purpose of this example, we&rsquo;ll add everything directly in the code-behind. And how do we locate the code-behind?  For example, if your XAML file is called MainPage.xaml, the code-behind is in MainPage.xaml.cs.</p><h3 id="variable-declaration">Variable Declaration</h3><p>➖ <strong>WindowSize:</strong> This variable allows us to control how many heartbeats can be displayed on the screen at the same time. The higher this value is, the more heartbeats will be visible before they move out of view. As a result, a larger WindowSize makes the heartbeat appear slower on the monitor.</p><p>➖ <strong>Beat:</strong> We define an array to represent a complete heartbeat. Values close to zero represent the baseline, while higher values represent the peaks.</p><p>➖ <strong>_samples:</strong> This variable represents what should be displayed on the screen. Initially, we fill it with zeros to display a flat line.</p><p>➖ <strong>EcgDrawable:</strong> This holds the object responsible for drawing the monitor signal.</p><p>➖ <strong>_i:</strong> Finally, we have the index that will be used to iterate through the Beat array.</p><pre class=" language-csharp"><code class="prism  language-csharp">// Variables
 
const int WindowSize = 140; 
static readonly float[] Beat = 
    { 
    0,0,0, .12f,.25f,.12f, 0, -.25f,1f,-.35f, 0,0, .20f,.35f,.20f, 0,0,0,0 
};

readonly List&lt;float&gt; _samples = Enumerable.Repeat(0f, WindowSize).ToList(); 
readonly EcgDrawable _drawable; 
int _i;
</code></pre><h3 id="continuing-with-the-constructor">Continuing with the Constructor</h3><p>Once we have all the required variables defined, the next step is to connect the components and start the animation inside the constructor.</p><p>First, we create an instance of <code>EcgDrawable</code> and assign it to the <code>GraphicsView</code>. This allows the view to know how to render the ECG signal based on the provided samples.</p><p>Next, we configure a timer using the Dispatcher. This timer is responsible for updating the signal at a regular interval, which helps us achieve a smooth and continuous animation.</p><p>On each timer tick:</p><ul><li>The next value from the heartbeat pattern is added to the samples list.</li><li>The window size is preserved by removing the oldest value.</li><li>The <code>GraphicsView</code> is invalidated to force a redraw.</li></ul><p>Finally, we start the timer, and the heart monitor animation begins automatically.</p><p>In code, it looks like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">public HeartAnimations() 
{ 
    InitializeComponent(); 
    _drawable = new EcgDrawable(_samples); 
    Ecg.Drawable = _drawable; 
    var t = Dispatcher.CreateTimer(); 
    t.Interval = TimeSpan.FromMilliseconds(16); 
    t.Tick += (_, __) =&gt; 
    { 
    _samples.Add(Beat[_i++ % Beat.Length]); 
    if (_samples.Count &gt; WindowSize) _samples.RemoveAt(0); 
    Ecg.Invalidate(); 
    }; 
    t.Start(); 
}
</code></pre><p>Finally, let&rsquo;s add the <code>EcgDrawable</code> class.</p><p>This class is responsible for <strong>visually rendering the ECG signal</strong> inside the GraphicsView component. It takes the list of values that represent the heart signal and transforms them into a continuous line, automatically calculating:</p><ul><li>The vertical position of the signal</li><li>The horizontal distribution of each point</li></ul><p>In code, this translates to the following:</p><pre class=" language-csharp"><code class="prism  language-csharp">class EcgDrawable(IReadOnlyList&lt;float&gt; samples) : IDrawable 
{ 
    public void Draw(ICanvas c, RectF r) 
    { 
    if (samples.Count &lt; 2) return; 
    c.StrokeColor = Colors.Red; 
    c.StrokeSize = 2; 
    var baseline = r.Top + r.Height * .55f; 
    var amp = r.Height * .35f; 
    var dx = r.Width / (samples.Count - 1); 
    var p = new PathF(); 
    p.MoveTo(r.Left, baseline - samples[0] * amp);  
    for (int i = 1; i &lt; samples.Count; i++) 
    p.LineTo(r.Left + i * dx, baseline - samples[i] * amp);
     
    c.DrawPath(p); 
    } 
}
</code></pre><p>And that&rsquo;s it!  We&rsquo;ve just finished building the Heart ECG Monitor animation. See? It wasn&rsquo;t that hard! I encourage you to try it out and experiment with it on your own.</p><p>Now, let&rsquo;s move on to the next animation! </p><h2 id="heart-ripple-pulse">2. Heart Ripple Pulse</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/02-heartripple.gif?sfvrsn=bc351843_2" title="Heart Ripple Pulse" alt="Heart Ripple Pulse" /></p><p>This animation represents the heartbeat and the waves generated by that pulse.</p><p>Here, we combine several simple animations and use a Grid as the main container to overlay all the elements in the same space, making them feel like a single, unified animation.</p><p>We&rsquo;ll start with the XAML, where we will define:</p><p>➖ Two Border components in red color, representing the ripple waves.</p><p>➖ A heart image, which will act as the main element at the center.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid HorizontalOptions="Center" 
    VerticalOptions="Start" 
    Margin="0,100" 
    WidthRequest="140" 
    HeightRequest="140"&gt;
    
    &lt;Border x:Name="Ripple1" 
    Stroke="Red" 
    StrokeThickness="3" 
    Opacity="0" 
    Scale="0.2" 
    StrokeShape="RoundRectangle 999" /&gt;
     
    &lt;Border x:Name="Ripple2" 
    Stroke="Red" 
    StrokeThickness="3" 
    Opacity="0" 
    Scale="0.2" 
    StrokeShape="RoundRectangle 999" /&gt;
     
    &lt;Image x:Name="Heart" 
    Source="redheart.png" 
    WidthRequest="48" 
    HeightRequest="48" 
    HorizontalOptions="Center" 
    VerticalOptions="Center" /&gt;

&lt;/Grid&gt;
</code></pre><p>To bring our animation to life, we&rsquo;ll work with the OnAppearing and in a method called Loop.</p><p>➖ <strong>OnAppearing:</strong> To explore something different, this time we&rsquo;ll work with the <code>OnAppearing</code> method (✍️ please make sure to declare the <code>_running</code> bool variable).</p><p>When the screen appears, we call the <code>Loop</code> method, which is responsible for running the animation cycle.</p><pre class=" language-csharp"><code class="prism  language-csharp">protected override void OnAppearing() 
{ 
    base.OnAppearing(); 
    _running = true; 
    _ = Loop(); 
}
</code></pre><p>➖ <strong>Loop():</strong> This is where the magic happens. ✨ Inside this method:</p><ul><li>We trigger the <strong>heart pop,</strong> a subtle scale effect on the heart</li><li>We animate the <strong>two circular lines</strong> to create the ripple effect</li><li>We use a <strong>delay</strong> to give each animation enough time and make them clearly distinguishable</li></ul><p>Thanks to this approach, we achieve a smooth, easy-to-follow and well-synchronized animation.</p><p>In code, this would look like the following:</p><pre class=" language-csharp"><code class="prism  language-csharp">async Task Loop() 
{ 
    while (_running) 
    { 
    // Reset 
    Ripple1.Opacity = Ripple2.Opacity = 0; 
    Ripple1.Scale = Ripple2.Scale = 0.2; 
    Heart.Scale = 1;
     
    // Heart pop 
    _ = Heart.ScaleTo(1.12, 90, Easing.CubicOut)
    
    .ContinueWith(_ =&gt; MainThread.InvokeOnMainThreadAsync( 
    () =&gt; Heart.ScaleTo(1.0, 120, Easing.CubicInOut)));
    
    // Ripple 1 
    _ = Task.WhenAll( 
    Ripple1.FadeTo(0.45, 60, Easing.CubicOut), 
    Ripple1.ScaleTo(1.8, 700, Easing.CubicOut) 
    ).ContinueWith(_ =&gt; MainThread.InvokeOnMainThreadAsync( 
    () =&gt; Ripple1.FadeTo(0, 250, Easing.CubicIn)));

    // Ripple 2 
    await Task.Delay(120); 
    _ = Task.WhenAll( 
    Ripple2.FadeTo(0.35, 60, Easing.CubicOut), 
    Ripple2.ScaleTo(1.8, 700, Easing.CubicOut) 
    ).ContinueWith(_ =&gt; MainThread.InvokeOnMainThreadAsync( 
    () =&gt; Ripple2.FadeTo(0, 250, Easing.CubicIn)));
     
    await Task.Delay(650); 
    } 
}
</code></pre><p>And that&rsquo;s it! Let&rsquo;s keep going and jump into the next animation! </p><h2 id="blinking-heart">3. Blinking Heart</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/03-blinkingheart.gif?sfvrsn=12221562_2" title="Blinking Heart" alt="Blinking Heart" /></p><p>In this animation, we&rsquo;ll make a heart blink in a subtle and elegant way. We&rsquo;ll start with the XAML. In this case, the structure is very simple, since we only need a single heart image, centered on the screen. From this single element, we&rsquo;ll build the entire animation.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Image x:Name="Heart"  
    Source="redheart.png"  
    WidthRequest="56"  
    HeightRequest="56"  
    HorizontalOptions="Center"  
    VerticalOptions="Center" /&gt;
</code></pre><p>We&rsquo;ll continue working with <code>OnAppearing</code> to start the animation, and additionally we&rsquo;ll create a method called <code>BlinkLoop()</code> to handle the animation logic. This one is composed of <code>FadeTo</code> and <code>ScaleTo</code> animations, which allow us to play with the icon&rsquo;s opacity and size, creating the blinking effect.</p><p>In code, it would look like the following:</p><pre class=" language-csharp"><code class="prism  language-csharp">protected override void OnAppearing() 
{ 
    base.OnAppearing(); 
    _running = true; 
    _ = BlinkLoop(); 
} 
async Task BlinkLoop() 
{

    while (_running) 
    { 
    await Task.WhenAll( 
    Heart.FadeTo(0.35, 220, Easing.CubicInOut), 
    Heart.ScaleTo(0.95, 220, Easing.CubicInOut) 
    ); 
    
    await Task.WhenAll( 
    Heart.FadeTo(1, 220, Easing.CubicInOut), 
    Heart.ScaleTo(1, 220, Easing.CubicInOut) 
    ); 
    } 
}
</code></pre><p>All set! Ready to move on to the next animation ✨</p><h2 id="rotating-heart">4. Rotating Heart</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/04-rotateheart.gif?sfvrsn=59e48923_2" title="Rotate Heart" alt="Rotate Heart" /></p><p>Now we&rsquo;ll create an animation where our heart rotates. ❤️ This type of animation is very useful, for example, as a loading indicator in your screens.</p><p>To get started with the implementation, we&rsquo;ll begin by adding the Image in XAML, as shown below:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Image x:Name="Heart" 
    Source="redheart.png" 
    WidthRequest="64" 
    HeightRequest="64" 
    HorizontalOptions="Center" 
    VerticalOptions="Center" /&gt;
</code></pre><p>And in the code-behind, it&rsquo;s time to bring the heart to life! ❤️</p><p>We&rsquo;ll use the <code>OnAppearing</code> method, and for the animation (✍️ please make sure to declare the <code>_isRunning</code> bool variable), we&rsquo;ll rely on <code>RotateTo()</code>, as shown below:</p><pre class=" language-csharp"><code class="prism  language-csharp">protected override async void OnAppearing() 
{ 
    base.OnAppearing(); 
    _isRunning = true; 
    
    while (_isRunning) 
    { 
    await Heart.RotateTo(360, 4000, Easing.Linear); 
    Heart.Rotation = 0; 
    } 
}
</code></pre><p>Done! Let&rsquo;s bring the next animation to life ✨</p><h2 id="jumping-heart">5. Jumping Heart</h2><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-04/05-heartjumping.gif?sfvrsn=5be8d95b_2" title="Heart Jumping" alt="Heart Jumping" /></p><p>For our final animation, we&rsquo;ll make the heart jump up and down in a continuous loop.</p><p>This animation also works great as a loading indicator, adding a playful touch to your screen.</p><p>Let&rsquo;s start by adding the Image to the XAML:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Image x:Name="Heart" 
    Source="redheart.png" 
    WidthRequest="64" 
    HeightRequest="64" 
    HorizontalOptions="Center" 
    VerticalOptions="Center" /&gt;
</code></pre><p>In the code-behind, we&rsquo;ll create the animation by working with <code>TranslationTo</code> and the <code>TranslationY</code> methods, as shown below:</p><pre class=" language-csharp"><code class="prism  language-csharp">protected override async void OnAppearing() 
{ 
    base.OnAppearing(); 
    _isRunning = true; 
    Heart.TranslationY = -120;
 
    while (_isRunning)
    
    { 
    await Heart.TranslateTo(0, 0, 600, Easing.CubicOut); 
    await Heart.TranslateTo(0, -12, 120, Easing.CubicInOut); 
    await Heart.TranslateTo(0, 0, 120, Easing.CubicInOut); 
    await Heart.TranslateTo(0, -120, 450, Easing.CubicIn); 
    } 
}
</code></pre><p>And that&rsquo;s all&mdash;thanks for building this with me! </p><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  We&rsquo;ve successfully created <strong>five awesome, ready-to-use animations</strong> with .NET MAUI. Each one was designed to be easy to implement, demonstrating just how powerful even the most basic animations can be when used correctly.</p><p>I hope this article has inspired you and sparked <strong>new ideas</strong> for incorporating animations into your current and future <strong>.NET MAUI projects ✨</strong></p><p>As always, if you have any questions or would like me to explore any of these animations in more detail, feel free to leave a comment &mdash; I&rsquo;d 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">Building an Instagram-Style Like Animation in .NET MAUI</h4></div><div class="col-8"><p class="u-fs16 u-mb0">Learn how to make your .NET MAUI app a little more engaging with interactive animations. We&rsquo;ll see how to <a target="_blank" href="https://www.telerik.com/blogs/building-instagram-style-like-animation-net-maui">animate a heart for a like action</a>.</p></div></div></aside><img src="https://feeds.telerik.com/link/23059/17352785.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:6808d742-f423-4697-ad7b-0da3008181c4</id>
    <title type="text">Share Functionality in Your .NET MAUI Apps</title>
    <summary type="text">Learn how to add share functionality to your .NET MAUI app whether in iOS, Android or Windows.</summary>
    <published>2026-05-26T13:50:18Z</published>
    <updated>2026-07-12T06:22:21Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17348725/share-functionality-net-maui-apps"/>
    <content type="text"><![CDATA[<p><span class="featured">Learn how to add share functionality to your .NET MAUI app whether in iOS, Android or Windows.</span></p><p>In recent years, many large companies have decided to rely on technology and move a big part&mdash;or even all&mdash;of their processes to mobile applications.</p><p>For example, not long ago, sending money from one bank account to another meant physically going to the bank and spending hours waiting in line. Today, that same process can be completed in just a few seconds using a mobile app. </p><p><strong>But&hellip; What happens next? </strong></p><p>How do we send a confirmation or receipt to the account owner so they can validate the transfer?</p><p>To solve this, applications usually include a <strong>share</strong> functionality, which allows users to send information through the familiar share sheet we all know&mdash;via WhatsApp, email, social media and more.</p><p>It&rsquo;s important to design the user experience from start to finish. It&rsquo;s not just about completing an action, but also about enabling users to easily share or confirm the result of that action.</p><p>In this article, you&rsquo;ll learn how to open the share sheet in your .NET MAUI apps, so you can share information quickly and effortlessly.</p><h2 id="what-is-ishare">What Is IShare?</h2><p>IShare is an interface that provides an API that allows you to share data such as links, files or text using the system&rsquo;s share functionality. When invoked, it opens a button sheet where the user can choose how and with whom they want to share that information.</p><p>The IShare interface is already available through the <code>Share.Default</code> property and is located in the Microsoft.Maui.ApplicationModel.DataTransfer namespace.</p><p>When the user interacts with this feature, they will see something like the following:</p><p><img sf-image-responsive="true" src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-05/share.png?sfvrsn=a83f43eb_2" height="500" style="max-width:100%;height:auto;" title=".NET MAUI share" width="1136" alt=".NET MAUI share in Android, iOS, Windows" sf-size="113426" /></p><p><span style="font-size:11px;">Image obtained from the official documentation.</span></p><h3 id="platform-settings">Platform Settings</h3><p>To implement the share functionality, some platforms require additional configuration. These are the supported platforms and their requirements:</p><ul><li><strong>Android and Windows:</strong> No setup is required.</li><li><strong>iOS / Mac Catalyst:</strong> To be able to access photos and videos, you need to add the appropriate permissions. To do this, go to:
        <ul><li>Platforms/iOS/Info.plist</li><li>And Platforms/MacCatalyst/Info.plist</li></ul></li></ul><p>Then add the permission keys along with their descriptions. Keep in mind that this description will be shown to the user when requesting permission, so it&rsquo;s important to use clear and user-friendly text. Below is an example of how the configuration should look:</p><pre><code>&lt;key&gt;NSPhotoLibraryAddUsageDescription&lt;/key&gt; 
&lt;string&gt;This app needs access to the photo gallery to save photos and videos.&lt;/string&gt; 

&lt;key&gt;NSPhotoLibraryUsageDescription&lt;/key&gt; 
&lt;string&gt;This app needs access to the photo gallery to save photos and videos.&lt;/string&gt;
</code></pre><h2 id="what-information-can-i-share-">What Information Can I Share? </h2><p>You can share text, links, files or even multiple files at the same time, depending on your needs. .NET MAUI provides different request types to handle each scenario.</p><p>Below are the most common use cases and how to implement them.</p><h3 id="-text"> Text</h3><p>To share plain text, you can use the <code>ShareTextRequest</code> class. This allows you to pass the text you want to share along with a title.</p><pre><code>public async Task ShareText(string text) 
{ 
    await Share.Default.RequestAsync(new ShareTextRequest 
    { 
    Text = text, 
    Title = "I&rsquo;m the title" 
    }); 
}
</code></pre><h3 id="-links"> Links</h3><p>You can also share a link by using the <code>Uri</code> property of <code>ShareTextRequest</code>. Simply provide the URI and a title.</p><pre><code>public async Task ShareUri(string uri, IShare share) 
{ 
    await share.RequestAsync(new ShareTextRequest 
    { 
    Uri = uri, 
    Title = "I&rsquo;m the title" 
    }); 
}
</code></pre><h3 id="-files"> Files</h3><p>.NET MAUI automatically detects the file type (MIME) and handles the sharing process accordingly. However, keep in mind that each operating system may decide whether a specific file type can be shared or not, depending on platform restrictions.</p><p>To share a single file, use the <code>ShareFileRequest</code> type, as shown below:</p><pre><code>public async Task ShareFile() 
{ 
    string fn = "MyFile.txt"; 
    string file = Path.Combine(FileSystem.CacheDirectory, fn); 
    File.WriteAllText(file, "This is a file"); 
    await Share.Default.RequestAsync(new ShareFileRequest 
    { 
    Title = "Share text file", 
    File = new ShareFile(file) 
    }); 
}
</code></pre><h3 id="️-multiple-files">️ Multiple Files</h3><p>Oh yeah!!  We also have the option to share multiple files using the <code>ShareFileRequest</code> type. Let&rsquo;s look at the following example:</p><pre><code>public async Task ShareMultipleFiles() 
{ 
    string file1 = Path.Combine(FileSystem.CacheDirectory, "File1.txt"); 
    string file2 = Path.Combine(FileSystem.CacheDirectory, "File2.txt");  
    File.WriteAllText(file1, "Hello 1"); 
    File.WriteAllText(file2, "Hello 2");
     
    await Share.Default.RequestAsync(new ShareMultipleFilesRequest 
    { 
    Title = "I&rsquo;m sharing multiple files", 
    Files = new List&lt;ShareFile&gt; { new ShareFile(file1), new ShareFile(file2) } 
    }); 
}
</code></pre><h2 id="android-control-file-locations">Android Control File Locations</h2><p>On Android, there are scenarios where a file is located in the app&rsquo;s private storage. In these cases, Android temporarily copies the file to the app cache and shares it using a FileProvider.</p><p>This behavior is very useful, but it&rsquo;s important to be careful. If it&rsquo;s not configured correctly, it can expose more information than intended, including data that should not be publicly accessible.</p><p>The good news is that this can be prevented by following the steps below.</p><h3 id="step-1-add-the-fileprovider-path-file">Step 1: Add the FileProvider Path File</h3><p>Inside the following folder:</p><pre><code>Platforms/Android/Resources/xml
</code></pre><p>And add a file with the exact name:</p><p><code>microsoft_maui_essentials_fileprovider_file_paths.xml</code></p><h3 id="step-2-what-will-this-file-contain">Step 2: What Will This File Contain?</h3><p>This file defines the allowed locations from which files can be shared.</p><p>Example configuration:</p><pre><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt; 
&lt;paths&gt; 
    &lt;external-path name="external_files" path="sharing-root" /&gt; 
    &lt;cache-path name="internal_cache" path="sharing-root" /&gt; 
    &lt;external-cache-path name="external_cache" path="sharing-root" /&gt; 
&lt;/paths&gt;
</code></pre><p><strong>What does each line mean?</strong></p><ul><li><strong><code>&lt;external-path&gt;:</code></strong> Allows sharing files from external storage. Useful when the file is stored in a location accessible to the user.</li><li><strong><code>&lt;cache-path&gt;:</code></strong> Allows sharing files from the app&rsquo;s internal cache. This is the most common and safest option, ideal for temporary files such as PDFs, images, or receipts.</li><li><strong><code>&lt;external-cache-path&gt;:</code></strong> Allows sharing files from the external cache. It is still a temporary location, but outside the internal storage.</li><li><strong>sharing-root:</strong> Is a folder that you define and that acts as a <strong>secure area for sharing files.</strong> Only files located inside this folder can be shared.</li></ul><h2 id="ipados-presentation-location">iPadOS Presentation Location</h2><p>When requesting a share or opening launcher on iPadOS, the system displays the action as a popover. To control where this popover appears on the screen and where its arrow points, you must specify a position using the <code>PresentationSourceBounds</code> property.</p><p>You can do it in the following way:</p><p><strong>Share</strong></p><pre><code>await Share.RequestAsync(new ShareFileRequest 
{ 
    Title = Title, 
    File = new ShareFile(file), 
    PresentationSourceBounds = 
    DeviceInfo.Platform == DevicePlatform.iOS &amp;&amp; 
    DeviceInfo.Idiom == DeviceIdiom.Tablet 
    ? new Rect(0, 20, 0, 0) 
    : Rect.Zero 
});
</code></pre><p><strong>Launcher</strong></p><pre><code>await Launcher.OpenAsync(new OpenFileRequest 
{ 
    File = new ReadOnlyFile(file), 
    PresentationSourceBounds = 
    DeviceInfo.Platform == DevicePlatform.iOS &amp;&amp; 
    DeviceInfo.Idiom == DeviceIdiom.Tablet 
    ? new Rect(0, 20, 0, 0) 
    : Rect.Zero 
})
</code></pre><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, you learned how to implement share functionality in your .NET MAUI apps, allowing users to easily share text, links, files and even multiple files across platforms.</p><p>You also explored important platform-specific considerations, such as additional permissions on iOS and Mac Catalyst, secure file sharing on Android using FileProvider, and how to properly handle popover presentation on iPadOS to avoid unexpected issues.</p><p>With these concepts in mind, you now have a clearer understanding of how to create a complete and secure sharing experience, taking care of both user experience and platform requirements.</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="reference">Reference</h3><p>Sample codes and explanation was based on the official documentation:</p><ul><li><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/data/share?view=net-maui-10.0&amp;tabs=android">https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/data/share?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><img src="https://feeds.telerik.com/link/23059/17348725.gif" height="1" width="1"/>]]></content>
  </entry>
  <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-07-12T06:22:21Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17343481/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><img src="https://feeds.telerik.com/link/23059/17343481.gif" height="1" width="1"/>]]></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-07-12T06:22:21Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17338393/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><img src="https://feeds.telerik.com/link/23059/17338393.gif" height="1" width="1"/>]]></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-07-12T06:22:21Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17332286/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><img src="https://feeds.telerik.com/link/23059/17332286.gif" height="1" width="1"/>]]></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-07-12T06:22:21Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17326534/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><img src="https://feeds.telerik.com/link/23059/17326534.gif" height="1" width="1"/>]]></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-07-12T06:22:21Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17318464/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><img src="https://feeds.telerik.com/link/23059/17318464.gif" height="1" width="1"/>]]></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-07-12T06:22:21Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17312599/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><img src="https://feeds.telerik.com/link/23059/17312599.gif" height="1" width="1"/>]]></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-07-12T06:22:21Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17304773/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><img src="https://feeds.telerik.com/link/23059/17304773.gif" height="1" width="1"/>]]></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-07-12T06:22:21Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17300341/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><img src="https://feeds.telerik.com/link/23059/17300341.gif" height="1" width="1"/>]]></content>
  </entry>
</feed>
