<?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:b3a3254f-56b8-4ac0-986f-f2830d0fea25;id=3266</id>
  <updated>2026-10-16T23:38:55Z</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:47ac6a3c-cdbf-49c3-baf9-8acb0f106edb</id>
    <title type="text">Getting Started with the .NET MAUI Map Control</title>
    <summary type="text">See how the Telerik UI for .NET MAUI Map control lets you display maps, labels and regions to add things like world maps or seating charts to your apps.</summary>
    <published>2026-10-13T16:07:29Z</published>
    <updated>2026-10-16T23:38:55Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17496519/getting-started-net-maui-map-control"/>
    <content type="text"><![CDATA[<p><span class="featured">See how the Telerik UI for .NET MAUI Map control lets you display maps, labels and regions to add things like world maps or seating charts to your apps.</span></p><p>In the world of web development, there are applications for displaying geographic information. Although there are ways to embed Google Maps or similar options, customizing them isn&rsquo;t so easy when you need to highlight geographic areas or respond to user selection. Fortunately, the Progress Telerik UI library has a <a target="_blank" href="https://www.telerik.com/maui-ui/map">.NET MAUI Map</a> control, which we will examine throughout this article. Let&rsquo;s get started!</p><h2 id="what-is-the-telerik-ui-for-.net-maui-map-control">What Is the Telerik UI for .NET MAUI Map Control?</h2><p>The Telerik .NET MAUI Map control is a powerful control for displaying maps in your .NET MAUI applications, with a lot of flexible styling options. It also supports multiple layers, pan and zoom, and many other features.</p><p>The control works with <strong>ESRI shapefiles</strong>, which are a standard vector format in geographic information systems or GIS. According to the <a target="_blank" href="https://www.telerik.com/maui-ui/map">MAUI Map documentation</a>, these files consist of geometric objects such as lines, polylines and polygons. This makes it possible to display different types of objects like floor plans and seat distribution, up to parts of country maps, roads, rivers, etc.</p><p>It&rsquo;s important to note that an ESRI shapefile is composed of two files:</p><ul><li>A <code>.shp</code> file, which contains the polygons that draw something on the map, such as a country, a region or a custom shape</li><li>A <code>.dbf</code> file, which contains the attributes associated with each geometry, such as the country&rsquo;s name or its population</li></ul><p>The control uses SkiaSharp to render the shapefile geometries, allowing fast and consistent rendering across platforms.</p><p>Finally, you should know that the .NET MAUI Map control is based on the use of layers, where each layer represents a data source that overlays the map. Let&rsquo;s see how to integrate this control into a .NET MAUI app.</p><h2 id="integrating-the-telerik-.net-maui-map-control-into-.net-maui-apps">Integrating the Telerik .NET MAUI Map Control into .NET MAUI Apps</h2><p>To see the control&rsquo;s features in action, we&rsquo;ll create a new project selecting the <strong>.NET MAUI App</strong> template, making sure not to include the sample code. Once the project is created, you can follow the <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/quickstart">installation guide for Telerik controls in .NET MAUI projects</a>, which will allow you to use Telerik controls in your project.</p><p>Next, we will install the following NuGet package in the project:</p><pre class=" language-text"><code class="prism  language-text">CommunityToolkit.Mvvm
</code></pre><p>This package will help reduce repetitive code in view models. With this, we are ready to integrate a map into our application.</p><h2 id="downloading-the-map-data">Downloading the Map Data</h2><p>As I mentioned earlier, the map control needs a shapefile to be able to draw the map. To simplify this guide, we will download the files <code>world.shp</code> and <code>world.dbf</code> that Progress Telerik has made available to us in the <a target="_blank" href="https://github.com/telerik/maui-samples/tree/main/Samples/SdkBrowser/Examples/MapControl">examples repository</a>.</p><p>To be able to use the downloaded files, let&rsquo;s create a new folder in <code>Resources/Maps</code>, where we will add the files <code>.shp</code> and <code>.dbf</code>. In addition, we must mark the files as embedded resources, which we will achieve by modifying your project file <code>.csproj</code> 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>ItemGroup</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>EmbeddedResource</span> <span class="token attr-name">Include</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Resources\Maps\*.shp<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>EmbeddedResource</span> <span class="token attr-name">Include</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Resources\Maps\*.dbf<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>ItemGroup</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>With the above, we will be able to use future additional map files without configuring each file as embedded. Also, we mark them as <code>EmbeddedResource</code> so that they are packaged inside the app assembly, which will allow us to read them later.</p><h2 id="creating-a-demo-view-model">Creating a Demo View Model</h2><p>With the map files added, the next step will be to create a view model that allows storing information about a country selected by the user. For this, we will define a file <code>MainViewModel.cs</code> with the following 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">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 punctuation">[</span><span class="token function">NotifyPropertyChangedFor</span><span class="token punctuation">(</span><span class="token function">nameof</span><span class="token punctuation">(</span>HasNoSelection<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">bool</span> hasSelection<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> selectedCountry <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> selectedPopulation <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">bool</span> HasNoSelection <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token operator">!</span>HasSelection<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>The above code defines properties to determine if there is a selection, a selected country and a selected population. The property <code>HasNoSelection</code> will allow showing a message when no country has been selected yet.</p><h2 id="displaying-the-map-in-a-contentpage">Displaying the Map in a ContentPage</h2><p>The time has come to display the map in the application. To do this, we will open the <code>ContentPage</code> file where we want to show the map, and replace its content with 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>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>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><span class="token namespace">telerik:</span>RadMap</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>map<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>0<span class="token punctuation">"</span></span>
            <span class="token attr-name">InteractionMode</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>PanAndZoom<span class="token punctuation">"</span></span>
            <span class="token attr-name">MaxZoomLevel</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">MinZoomLevel</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><span class="token namespace">telerik:</span>RadMap.Layers</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>MapShapefileLayer</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>shapeLayer<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>MapShapefileLayer.Reader</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>MapShapeReader</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>reader<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>MapShapefileLayer.Reader</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>MapShapefileLayer</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>RadMap.Layers</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>RadMap</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>ContentPage</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>In the above code, you can see that we use properties of the map control, such as <code>MinZoomLevel</code> and <code>MaxZoomLevel</code> to limit the zoom range, in addition to <code>InteractionMode</code> to enable panning and zoom with gestures.</p><p>Additionally, we use the <code>RadMap.Layers</code> tag to add a <code>MapShapefileLayer</code> type, which will read the shapefile. We also use a <code>MapShapeReader</code> type named <code>reader</code>, which will be responsible for loading the files <code>.shp</code> and <code>.dbf</code>.</p><p>Now, we must load the files from the code behind of the page where we defined the map, 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">MainPage</span> <span class="token punctuation">:</span> ContentPage
<span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">readonly</span> MainViewModel viewModel<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>

        <span class="token keyword">this</span><span class="token punctuation">.</span>viewModel <span class="token operator">=</span> viewModel<span class="token punctuation">;</span>
        BindingContext <span class="token operator">=</span> viewModel<span class="token punctuation">;</span>

        <span class="token keyword">var</span> assembly <span class="token operator">=</span> <span class="token function">GetType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Assembly<span class="token punctuation">;</span>

        reader<span class="token punctuation">.</span>ReadCompleted <span class="token operator">+</span><span class="token operator">=</span> OnReadCompleted<span class="token punctuation">;</span>
        reader<span class="token punctuation">.</span>DataSource <span class="token operator">=</span> MapSource<span class="token punctuation">.</span><span class="token function">FromResource</span><span class="token punctuation">(</span><span class="token string">"TelerikMapDemo.Resources.Maps.world.dbf"</span><span class="token punctuation">,</span> assembly<span class="token punctuation">)</span><span class="token punctuation">;</span>
        reader<span class="token punctuation">.</span>Source <span class="token operator">=</span> MapSource<span class="token punctuation">.</span><span class="token function">FromResource</span><span class="token punctuation">(</span><span class="token string">"TelerikMapDemo.Resources.Maps.world.shp"</span><span class="token punctuation">,</span> assembly<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">OnReadCompleted</span><span class="token punctuation">(</span><span class="token keyword">object</span><span class="token operator">?</span> sender<span class="token punctuation">,</span> EventArgs e<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        reader<span class="token punctuation">.</span>ReadCompleted <span class="token operator">-</span><span class="token operator">=</span> OnReadCompleted<span class="token punctuation">;</span>
        Dispatcher<span class="token punctuation">.</span><span class="token function">Dispatch</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> map<span class="token punctuation">.</span><span class="token function">SetView</span><span class="token punctuation">(</span>shapeLayer<span class="token punctuation">.</span><span class="token function">GetBestView</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>In the above code, there are a few elements worth analyzing:</p><ul><li>We access the map information through a special class called <code>MapSource</code>, with which we load the map resources. Make sure to modify the namespace according to your project&rsquo;s name.</li><li>We subscribe to the <code>ReadCompleted</code> event before any map reading, so that the handler runs when the reading of the files finishes.</li><li>We use the properties <code>DataSource</code> and <code>Source</code> to load both the map and the geometries.</li><li>In the <code>OnReadCompleted</code> handler, we unsubscribe from the read event so that it only executes once, and also use the methods <code>SetView</code> and <code>GetBestView</code> to calculate the region with the best fit for all the geometries.</li></ul><p>Before running the application, we must go back to the <code>MauiProgram.cs</code> file and add to the dependency container the references for the content page and its view model</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">AddSingleton<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>
        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>MainPage<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 punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>Now, when running the application, we will be able to see the map control rendered correctly:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/telerik-maui-map-control.png?sfvrsn=4eddf316_2" alt="Telerik .NET MAUI map control displaying map view" /></p><h2 id="adding-labels-to-the-map">Adding Labels to the Map</h2><p>We have successfully added the map to our app. However, it doesn&rsquo;t display any information, which is not very useful.</p><p>The file <code>.dbf</code> contains information we can use to add additional data to the map, such as country names. To do this, we&rsquo;ll use an attribute called <code>CNTRY_NAME</code>, modifying the layer <code>MapShapefileLayer</code> to include the layer <code>LabelAttributeName</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>MapShapefileLayer</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>shapeLayer<span class="token punctuation">"</span></span> <span class="token attr-name">LabelAttributeName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>CNTRY_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>MapShapefileLayer</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>In the code above, the property <code>LabelAttributeName</code> allows adding a label for each shape in a <code>MapShapefileLayer</code>. When running the app, we can see the names on the map as shown below:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/sample-map-labels-demo.gif?sfvrsn=21ab2f93_2" alt="Close-up of sample labels displayed on a map control" /></p><p>In the demo above, you can see how when zooming the country labels gradually appear, allowing for a pleasant user experience.</p><h2 id="customizing-the-map">Customizing the Map</h2><p>So far, we have used the map&rsquo;s default style; however, in real apps you&rsquo;ll likely want to add colors for sections of your map. This is possible thanks to the use of <code>MapShapeStyleSelector</code>, which is a style selector that we can use to decide what colors to use for each region on the map.</p><p>In our example, we&rsquo;ll compare the population of each country to determine its color. To do this, we&rsquo;ll create a new class called<br /><code>PopulationShapeStyleSelector</code>, which will be defined as follows:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token keyword">using</span> IShape <span class="token operator">=</span> Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Controls<span class="token punctuation">.</span>ShapefileReader<span class="token punctuation">.</span>IShape<span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">PopulationShapeStyleSelector</span> <span class="token punctuation">:</span> MapShapeStyleSelector
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> MapShapeStyle HighPopulationStyle <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">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">public</span> MapShapeStyle MediumPopulationStyle <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">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">public</span> MapShapeStyle LowPopulationStyle <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">new</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">override</span> MapShapeStyle <span class="token function">SelectStyle</span><span class="token punctuation">(</span><span class="token keyword">object</span> shape<span class="token punctuation">,</span> BindableObject container<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>shape <span class="token keyword">is</span> fileReader<span class="token punctuation">.</span>IShape mapShape <span class="token operator">&amp;&amp;</span>
            <span class="token keyword">double</span><span class="token punctuation">.</span><span class="token function">TryParse</span><span class="token punctuation">(</span>mapShape<span class="token punctuation">.</span><span class="token function">GetAttribute</span><span class="token punctuation">(</span><span class="token string">"POP_CNTRY"</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">out</span> <span class="token keyword">var</span> population<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>population <span class="token operator">&gt;</span> 50_000_000<span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">return</span> HighPopulationStyle<span class="token punctuation">;</span>
            <span class="token punctuation">}</span>

            <span class="token keyword">if</span> <span class="token punctuation">(</span>population <span class="token operator">&lt;</span> 5_000_000<span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">return</span> LowPopulationStyle<span class="token punctuation">;</span>
            <span class="token punctuation">}</span>

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

        <span class="token keyword">return</span> LowPopulationStyle<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>The operation is similar to a common .NET MAUI Style Selector, that is, we define style references as part of the class, in this case <code>HighPopulationStyle</code>, <code>MediumPopulationStyle</code> and <code>LowPopulationStyle</code>.</p><p>Next, the attribute <code>POP_CNTRY</code> is obtained from each mapShape, which is evaluated to determine the style that will be applied.</p><p>With the selector defined, we still need to create the styles to be applied. We can do this from the <code>ContentPage</code> where we&rsquo;ve implemented the map control, 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>ContentPage</span> <span class="token attr-name">...</span>    
    <span class="token attr-name"><span class="token namespace">xmlns:</span>styling</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>clr-namespace:TelerikMapDemo.Styling<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">styling:</span>PopulationShapeStyleSelector</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>PopulationStyleSelector<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">styling:</span>PopulationShapeStyleSelector.HighPopulationStyle</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>MapShapeStyle</span>
                    <span class="token attr-name">FillColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#1E4C5C<span class="token punctuation">"</span></span>
                    <span class="token attr-name">StrokeColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#CFE8F2<span class="token punctuation">"</span></span>
                    <span class="token attr-name">StrokeWidth</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><span class="token namespace">styling:</span>PopulationShapeStyleSelector.HighPopulationStyle</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">styling:</span>PopulationShapeStyleSelector.MediumPopulationStyle</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>MapShapeStyle</span>
                    <span class="token attr-name">FillColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#3C99B7<span class="token punctuation">"</span></span>
                    <span class="token attr-name">StrokeColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#CFE8F2<span class="token punctuation">"</span></span>
                    <span class="token attr-name">StrokeWidth</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><span class="token namespace">styling:</span>PopulationShapeStyleSelector.MediumPopulationStyle</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">styling:</span>PopulationShapeStyleSelector.LowPopulationStyle</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>MapShapeStyle</span>
                    <span class="token attr-name">FillColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#95D3E8<span class="token punctuation">"</span></span>
                    <span class="token attr-name">StrokeColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#CFE8F2<span class="token punctuation">"</span></span>
                    <span class="token attr-name">StrokeWidth</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><span class="token namespace">styling:</span>PopulationShapeStyleSelector.LowPopulationStyle</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">styling:</span>PopulationShapeStyleSelector</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>ContentPage</span><span class="token punctuation">&gt;</span></span>    
</code></pre><p>You can see that we create an instance of <code>PopulationShapeStyleSelector</code>, within which we assign to each property of the selector a <code>MapShapeStyle</code>, which will allow customizing each defined selector.</p><p>The last step is to indicate that we want to use the selector we just created in <code>MapShapefileLayer</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>MapShapefileLayer</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>shapeLayer<span class="token punctuation">"</span></span>
    <span class="token attr-name">LabelAttributeName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>CNTRY_NAME<span class="token punctuation">"</span></span>
    <span class="token attr-name">ShapeStyleSelector</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{StaticResource PopulationStyleSelector}<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>MapShapefileLayer</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>The result of running it is as follows:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/map-control-region-coloring-demo.gif?sfvrsn=9c355e78_2" alt="Map control displaying colored regions" /></p><p>In the image above, you can see how the countries appear colored according to their population. Now, let&rsquo;s see how to select regions on a map.</p><h2 id="enabling-country-selection">Enabling Country Selection</h2><p>To make the map fully functional, we will allow users to select a country to view its information in detail. We&rsquo;ll do this by adding the use of the property <code>SelectionMode</code> in the <code>MapShapefileLayer</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>MapShapefileLayer</span> <span class="token attr-name">...</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>MapShapefileLayer.SelectedShapeStyle</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>MapShapeStyle</span> <span class="token attr-name">FillColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#F4B400<span class="token punctuation">"</span></span>
                               <span class="token attr-name">StrokeColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#8A6D00<span class="token punctuation">"</span></span>
                               <span class="token attr-name">StrokeWidth</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1.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><span class="token namespace">telerik:</span>MapShapefileLayer.SelectedShapeStyle</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>MapShapefileLayer</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>In the code above we have indicated that only one country can be selected at a time, although you could also use the value <code>Multiple</code> if you need the user to select more than one country. Likewise, we have defined a <code>MapShapeStyle</code> section, which is used to specify the characteristics of the selected region.</p><p>We will also complete the <code>ContentPage</code> of our app, adding a Telerik container <code>RadBorder</code> in the second row of the main grid, which will serve to display the selected country&rsquo;s information using standard controls and Telerik buttons:</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>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>20<span class="token punctuation">"</span></span>
    <span class="token attr-name">Background</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">BorderColor</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 attr-name">BorderThickness</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">CornerRadius</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16,16,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>VerticalStackLayout</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>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>Selected country<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>#607D8B<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>15<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 HasNoSelection}<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>Tap a country on the map to view its information.<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>#90A4AE<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 attr-name">IsVisible</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding HasSelection}<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>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>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>{Binding SelectedCountry}<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>#102A43<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>{Binding SelectedPopulation}<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>#455A64<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>HorizontalStackLayout</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">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16,10<span class="token punctuation">"</span></span>
                <span class="token attr-name">Background</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#1E4C5C<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>OnResetViewClicked<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>8<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>Overview<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">Padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16,10<span class="token punctuation">"</span></span>
                <span class="token attr-name">Background</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>#E3F2F8<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>OnClearSelectionClicked<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>8<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 selection<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>#1E4C5C<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>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>RadBorder</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>You also need to complete the code behind of the <code>ContentPage</code> to react to selection changes, as well as handle button actions:</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">private</span> <span class="token keyword">readonly</span> MainViewModel viewModel<span class="token punctuation">;</span>
    
    <span class="token keyword">public</span> <span class="token function">MainPage</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>

        <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
        shapeLayer<span class="token punctuation">.</span>SelectedShapes<span class="token punctuation">.</span>CollectionChanged <span class="token operator">+</span><span class="token operator">=</span> OnSelectedShapesChanged<span class="token punctuation">;</span>
        
        reader<span class="token punctuation">.</span>DataSource <span class="token operator">=</span> MapSource<span class="token punctuation">.</span><span class="token function">FromResource</span><span class="token punctuation">(</span><span class="token string">"TelerikMapDemo.Resources.Maps.world.dbf"</span><span class="token punctuation">,</span> assembly<span class="token punctuation">)</span><span class="token punctuation">;</span>
reader<span class="token punctuation">.</span>Source <span class="token operator">=</span> MapSource<span class="token punctuation">.</span><span class="token function">FromResource</span><span class="token punctuation">(</span><span class="token string">"TelerikMapDemo.Resources.Maps.world.shp"</span><span class="token punctuation">,</span> assembly<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">private</span> <span class="token keyword">void</span> <span class="token function">OnSelectedShapesChanged</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>shapeLayer<span class="token punctuation">.</span>SelectedShapes<span class="token punctuation">.</span>Count <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            viewModel<span class="token punctuation">.</span>HasSelection <span class="token operator">=</span> <span class="token keyword">false</span><span class="token punctuation">;</span>
            viewModel<span class="token punctuation">.</span>SelectedCountry <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>
            viewModel<span class="token punctuation">.</span>SelectedPopulation <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">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">var</span> shape <span class="token operator">=</span> shapeLayer<span class="token punctuation">.</span>SelectedShapes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

        viewModel<span class="token punctuation">.</span>SelectedCountry <span class="token operator">=</span> shape<span class="token punctuation">.</span><span class="token function">GetAttribute</span><span class="token punctuation">(</span><span class="token string">"CNTRY_NAME"</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">?</span><span class="token operator">?</span> <span class="token string">"Unknown"</span><span class="token punctuation">;</span>

        <span class="token keyword">var</span> populationText <span class="token operator">=</span> shape<span class="token punctuation">.</span><span class="token function">GetAttribute</span><span class="token punctuation">(</span><span class="token string">"POP_CNTRY"</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        viewModel<span class="token punctuation">.</span>SelectedPopulation <span class="token operator">=</span> <span class="token keyword">double</span><span class="token punctuation">.</span><span class="token function">TryParse</span><span class="token punctuation">(</span>populationText<span class="token punctuation">,</span> <span class="token keyword">out</span> <span class="token keyword">var</span> population<span class="token punctuation">)</span>
            <span class="token operator">?</span> $<span class="token string">"Approximate population: {population:N0} inhabitants"</span>
            <span class="token punctuation">:</span> <span class="token string">"Population not available"</span><span class="token punctuation">;</span>

        viewModel<span class="token punctuation">.</span>HasSelection <span class="token operator">=</span> <span class="token keyword">true</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">OnResetViewClicked</span><span class="token punctuation">(</span><span class="token keyword">object</span><span class="token operator">?</span> sender<span class="token punctuation">,</span> EventArgs e<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        map<span class="token punctuation">.</span><span class="token function">SetView</span><span class="token punctuation">(</span>shapeLayer<span class="token punctuation">.</span><span class="token function">GetBestView</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">private</span> <span class="token keyword">void</span> <span class="token function">OnClearSelectionClicked</span><span class="token punctuation">(</span><span class="token keyword">object</span><span class="token operator">?</span> sender<span class="token punctuation">,</span> EventArgs e<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        shapeLayer<span class="token punctuation">.</span>SelectedShapes<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>

<span class="token punctuation">}</span>
</code></pre><p>In the code above we subscribed to the <code>CollectionChanged</code> event, which will be fired when a user selects or deselects a country. In the event handler <code>OnSelectedShapesChanged</code> we validate whether there are selected shapes; if not, the graphical elements that display information about each country are cleared.</p><p>If a country has been selected, the attributes <code>CNTRY_NAME</code> and <code>POP_CNTRY</code> are read and the values in the view model are updated.</p><p>Finally, we also create the event handlers <code>OnResetViewClicked</code> for a button that allows recentering the entire map using the method <code>GetBestView()</code> again. We have also defined the method <code>OnClearSelectionClicked</code>, which will be used to clear the <code>SelectedShapes</code> collection, to deselect any selected country and reset the data in the UI:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/dotnet-maui-map-country-selection.gif?sfvrsn=c0d1b5f5_2" alt="Map control with country selection enabled" /></p><p>In the image above we can see how, when selecting a country on the map, its information is correctly displayed at the bottom.</p><h2 id="conclusion">Conclusion</h2><p>In this article you got to know the Telerik UI Map control for .NET MAUI, which is an excellent option for displaying maps, labels and regions reliably and quickly. We saw step by step how to read ESRI shapefiles as well as render them.</p><p>We also learned how to color different regions using a style selector and how to allow users to select specific regions on the map.</p><p>Now it&rsquo;s your turn to create unique experiences using this powerful control. The whole Telerik UI for .NET MAUI suite comes with a free 30-day trial so you can explore it yourself.</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/17496519.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:269bcaca-43ab-495e-a3f4-e0cf0b825c37</id>
    <title type="text">Creating an Account UI in .NET MAUI</title>
    <summary type="text">See how to bring a user interface design for an account screen to life in a .NET MAUI application.</summary>
    <published>2026-09-28T20:43:49Z</published>
    <updated>2026-10-16T23:38:55Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17476715/creating-account-ui-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">See how to bring a user interface design for an account screen to life in a .NET MAUI application. </span></p><p>How many times a month do you create a new account? Probably more often than you remember. And while it may seem like a simple process, that first interaction can shape a user&rsquo;s perception of the entire app.</p><p>As developers, it&rsquo;s important to pay attention to every detail when transforming a design into code. Our goal isn&rsquo;t just to make the application work, but also to stay true to the original design and deliver a smooth, enjoyable user experience. That&rsquo;s why, in this article, we&rsquo;ll recreate two screens inspired by a <a target="_blank" href="https://dribbble.com/shots/27206083-Clean-Simple-Login-Register-Mobile-UI">Dribbble</a> design, bringing them to life step by step using .NET MAUI.</p><p>So grab a cup of coffee (or hot chocolate if you have a sweet tooth ☕), open Visual Studio or Visual Studio Code &hellip; <strong>and let&rsquo;s start coding! </strong></p><h2 id="how-will-the-explanation-work">How Will the Explanation Work?</h2><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 one will be explained individually.</p><p>➖ <strong>Code explanation per block:</strong> In addition to the written explanation, each screen includes a set of blocks with the exact code snippets you need to implement and achieve the final 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 this design, we took inspiration from an original Dribbble UI, but made some adaptations and adjustments to align it with the goals of this article.</p><h2 id="-environment-setup"> Environment Setup</h2><p>You&rsquo;ll learn how to take advantage of some of the powerful Progress Telerik UI for .NET MAUI components in this post. If you don&rsquo;t have the .NET MAUI library installed yet, visit the <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/quickstart">quick start page</a>, which explains step-by-step how to install Telerik UI for .NET MAUI, download the license key, configure the Telerik package source and install the Telerik MCP server (if needed).</p><h2 id="breaking-down-the-design">Breaking Down the Design</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 title="Visual structure" src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-09/01_create_account_structure.png?sfvrsn=5ad0128e_2" alt="Visual structure" /></p><h2 id="flower-image-step">1. Flower Image Step</h2><p>Let&rsquo;s start by creating the main page, which we&rsquo;ll call <strong>WelcomeBackPage.xaml.</strong> This one will contain the components from both Step 1 and Step 2. For the main layout, we&rsquo;ll use a Grid, divided into two rows.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid RowDefinitions="500,*"&gt;

    &lt;!-- Add blocks one and two here --&gt;

&lt;/Grid&gt;
</code></pre><p>This Grid is composed of the following elements:</p><p> <strong>Header image:</strong> In the first row, we&rsquo;ll add the background image using the <code>AspectFill</code> property, allowing it to fill the available width while maintaining an attractive appearance across different screen sizes.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Image Grid.Row="0" Source="bgroseflower.png" Aspect="AspectFill" /&gt;
</code></pre><p> <strong>Main container:</strong> In the second row, we&rsquo;ll add a Border control. In this case, we&rsquo;ll use the Telerik UI for <a target="_blank" href="https://www.telerik.com/maui-ui/border">.NET MAUI Border control</a>, so make sure to include the Telerik namespace in your page:</p><pre class=" language-xml"><code class="prism  language-xml">xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"
</code></pre><p>To create the overlapping effect, we only need to apply a negative top margin. This gives the impression that the white container is placed on top of the image. Finally, inside the Border, we&rsquo;ll add a <strong>VerticalStackLayout</strong>, which we&rsquo;ll use in the next steps to place the labels and buttons.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadBorder 
    Grid.Row="1" 
    Margin="0,-80" 
    Padding="30" 
    BackgroundColor="White" 
    CornerRadius="30"&gt;
 
    &lt;VerticalStackLayout 
    Spacing="15" 
    VerticalOptions="Fill" 
    HorizontalOptions="Center"&gt; 
    &lt;!-- Add block two here --&gt; 
    &lt;/VerticalStackLayout&gt; 
&lt;/telerik:RadBorder&gt;
</code></pre><p>And you&rsquo;ll get a result like this:</p><p><img title="Flower Image step" src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-09/02_create_account_structure_step_01.png?sfvrsn=42bf878e_2" alt="1. Flower Image step" /></p><h2 id="welcome-info-step">2. Welcome Info Step</h2><p>For this second step, we already have the foundation in place from the previous section when we added the <strong>VerticalStackLayout.</strong> This means that all the controls we&rsquo;ll add from this point forward should be placed inside that layout.</p><p>Let&rsquo;s start by adding the first three Label controls:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label 
    HorizontalTextAlignment="Center" 
    Text="Welcome Back!" 
    FontAttributes="Bold" 
    FontSize="26" 
    TextColor="Black" /&gt;
 
&lt;Label 
    HorizontalTextAlignment="Center" 
    Text="Hi there!" 
    FontSize="15" 
    TextColor="#8A8A8A" /&gt;
  
&lt;Label 
    HorizontalTextAlignment="Center" 
    FontSize="15" 
    TextColor="#8A8A8A" 
    Text="We're here to help you learn new skills.&amp;#10;The choice is yours; Log in or create account." /&gt;
</code></pre><h3 id="next-lets-add-the-buttons">Next, Let&rsquo;s Add the Buttons</h3><p>I have to admit, I absolutely <strong>love</strong> these buttons!  The soft gradient gives them a modern and elegant look that really makes the UI stand out.</p><p>To achieve this effect, we&rsquo;ll use .NET MAUI&rsquo;s <strong>LinearGradientBrush</strong> along with three gradient stops. This allows us to smoothly blend multiple colors and create the beautiful gradient shown in the design.</p><p>The implementation looks like this:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button 
    Text="Create Account" 
    TextColor="White" 
    FontSize="16" 
    HeightRequest="45" 
    CornerRadius="25"&gt; 
    &lt;Button.Background&gt; 
    &lt;LinearGradientBrush 
    StartPoint="0,0.5" 
    EndPoint="1,0.5"&gt; 
    &lt;GradientStop Color="#F8A8BC" Offset="0.0"/&gt; 
    &lt;GradientStop Color="#D0A6F7" Offset="0.5"/&gt; 
    &lt;GradientStop Color="#AF95F6" Offset="1.0"/&gt; 
    &lt;/LinearGradientBrush&gt; 
    &lt;/Button.Background&gt; 
&lt;/Button&gt;
</code></pre><p>✍️ If you want to learn more about <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/user-interface/brushes/lineargradient?view=net-maui-10.0"><strong>LinearGradientBrush</strong>, I recommend checking out this article</a>.</p><h3 id="the-login-button">The Login Button</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Button BorderColor="#AF95F6" 
    BackgroundColor="White" 
    BorderWidth="1" 
    CornerRadius="20" 
    Text="Log In" 
    HeightRequest="45" 
    TextColor="Black"/&gt;
</code></pre><p>Finally, let&rsquo;s add the label displayed for users who don&rsquo;t have an account yet. Notice that this text uses two different styles within the same label. Instead of creating two Label controls, we&rsquo;ll use a <strong>FormattedString</strong>, which allows us to apply multiple styles within a single Label.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label FontSize="13" HorizontalTextAlignment="Center"&gt; 
    &lt;Label.FormattedText&gt; 
    &lt;FormattedString&gt; 
    &lt;Span Text="Dont'have an account?"/&gt; 
    &lt;Span Text=" Sign Up" TextDecorations="Underline" TextColor="#AF95F6"/&gt; 
    &lt;/FormattedString&gt; 
    &lt;/Label.FormattedText&gt; 
&lt;/Label&gt;
</code></pre><p>And you&rsquo;ll get a result like this:</p><p><img title="Welcome Info step" src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-09/03_create_account_structure_step_02.png?sfvrsn=a56aa292_2" alt="2. Welcome Info step" /></p><h2 id="create-account-step">3. Create Account Step</h2><p>We made it to the third step, yay! </p><p>For this step, we&rsquo;ll create a new page called <strong>CreateAccountPage.xaml</strong>, which will contain all the elements needed for the account creation screen.</p><p>Just like the previous page, this screen also includes a header image and a white content container with rounded top corners.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid RowDefinitions="260,*"&gt; 
    &lt;Image Grid.Row="0" Source="bggreenflower.png" Aspect="AspectFill" /&gt;
    
    &lt;telerik:RadBorder 
    Grid.Row="1" 
    Margin="0,-80" 
    Padding="30" 
    BackgroundColor="White" 
    CornerRadius="30"&gt;
     
    &lt;VerticalStackLayout 
    Spacing="15" 
    VerticalOptions="Fill" 
    HorizontalOptions="Center"&gt; 
    &lt;!-- Add block three here --&gt; 
    &lt;/VerticalStackLayout&gt; 
    &lt;/telerik:RadBorder&gt; 
&lt;/Grid&gt;
</code></pre><p>Now, let&rsquo;s add the title and description:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label 
    HorizontalTextAlignment="Center" 
    Text="Create Account" 
    FontAttributes="Bold" 
    FontSize="20" 
    TextColor="Black" /&gt;

&lt;Label 
    HorizontalTextAlignment="Center" 
    FontSize="13" 
    FontAttributes="Bold" 
    Text="We're here to help you reach the peaks of learning.&amp;#10;Are you ready?" /&gt;
</code></pre><h3 id="let’s-add-the-form">Let&rsquo;s Add the Form</h3><p>For the form, we&rsquo;ll use <strong><a target="_blank" href="https://www.telerik.com/maui-ui/dataform">Telerik UI for .NET MAUI DataForm</a></strong>. This control works like magic and helps us save a lot of time when building forms! ✨</p><p>To use it in your XAML page, make sure to add the following namespace:</p><pre class=" language-xml"><code class="prism  language-xml">xmlns:telerik="clr-namespace:Telerik.Maui.Controls;assembly=Telerik.Maui.Controls"
</code></pre><h3 id="creating-the-model">Creating the Model</h3><p>The first step is to define a model that represents the data our form will collect. Each property includes attributes that describe how it should be displayed, whether it&rsquo;s required, and the type of data it accepts. The <strong>Telerik DataForm</strong> leverages these attributes to automatically generate the corresponding inputs and validation rules.</p><p>Our model should look like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">public class SignUp : NotifyPropertyChangedBase 
{ 
    private string email; 
    private string password; 
    private string confirmPassword;
     
    [Required] 
    [Display(Name = "Email")] 
    public string Email 
    { 
    get =&gt; email; 
    set =&gt; UpdateValue(ref email, value); 
    }
     
    [Required] 
    [Display(Name = "Password")] 
    [DataType(DataType.Password)] 
    public string Password 
    { 
    get =&gt; password; 
    set =&gt; UpdateValue(ref password, value); 
    }
     
    [Required] 
    [Display(Name = "Confirm Password")] 
    [DataType(DataType.Password)] 
    public string ConfirmPassword 
    { 
    get =&gt; confirmPassword; 
    set =&gt; UpdateValue(ref confirmPassword, value); 
    } 
}
</code></pre><p>The next step is to assign our model to the page&rsquo;s <code>BindingContext</code>. To keep the sample simple, we&rsquo;ll create a new instance of the SignUp model directly in the page constructor.</p><pre class=" language-csharp"><code class="prism  language-csharp">public CreateAccountPage() 
{ 
    InitializeComponent(); 
    this.BindingContext = new Models.SignUp(); 
}
</code></pre><h3 id="adding-it-in-xaml">Adding It in XAML</h3><p>Finally, we can add it to our XAML. Simply include the <strong>RadDataForm</strong> like the following:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadDataForm 
    x:Name="dataForm" 
    AutomationId="dataForm" /&gt;
</code></pre><p>That&rsquo;s it! Your dynamic form is now ready and fully integrated into your page. </p><h3 id="let’s-add-the-button">Let&rsquo;s Add the Button</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Button 
    Text="Sign Up" 
    TextColor="White" 
    FontSize="16" 
    HeightRequest="45" 
    CornerRadius="25"&gt; 
    &lt;Button.Background&gt; 
    &lt;LinearGradientBrush 
    StartPoint="0,0.5" 
    EndPoint="1,0.5"&gt; 
    &lt;GradientStop Color="#F8A8BC" Offset="0.0"/&gt; 
    &lt;GradientStop Color="#D0A6F7" Offset="0.5"/&gt; 
    &lt;GradientStop Color="#AF95F6" Offset="1.0"/&gt; 
    &lt;/LinearGradientBrush&gt; 
    &lt;/Button.Background&gt; 
&lt;/Button&gt;
</code></pre><h3 id="divider-and-text">Divider and Text</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid ColumnDefinitions="*,Auto,*"&gt; 

    &lt;BoxView 
    Grid.Column="0" 
    HeightRequest="0.2" 
    Color="#AF95F6"/&gt;
     
    &lt;Label 
    Grid.Column="1" 
    Text=" or continue with " 
    FontSize="15" 
    TextColor="#6E6E6E" /&gt;
     
    &lt;BoxView 
    Grid.Column="2" 
    HeightRequest="0.2" 
    Color="#AF95F6" /&gt; 
    
&lt;/Grid&gt;
</code></pre><h3 id="social-buttons">Social Buttons</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid 
    ColumnDefinitions="*,*" 
    ColumnSpacing="15" 
    HorizontalOptions="Fill"&gt; 
    &lt;Button 
    Grid.Column="0" 
    Text="Google" 
    ImageSource="googlecolor.png" 
    TextColor="Black" 
    FontSize="16" 
    HeightRequest="45" 
    CornerRadius="25" 
    BorderColor="LightGray" 
    BorderWidth="0.3" 
    HorizontalOptions="Fill" 
    BackgroundColor="White"/&gt;

    &lt;Button 
    Grid.Column="1" 
    Text="Apple" 
    ImageSource="apple.png" 
    TextColor="Black" 
    FontSize="16" 
    HeightRequest="45" 
    CornerRadius="25" 
    BorderColor="LightGray" 
    BorderWidth="0.3" 
    HorizontalOptions="Fill" 
    BackgroundColor="White"/&gt;

&lt;/Grid&gt;
</code></pre><p>And you&rsquo;ll get a result like this:</p><p><img title="Create account step" src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-09/04_create_account_structure_step_03.png?sfvrsn=a5ad3aa2_2" alt="3. Create account step" /></p><p>And that&rsquo;s it, we&rsquo;re all done!  Below, you can see the final result of both screens.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-09/05_create_account_structure_complete.png?sfvrsn=e2494639_2" alt="Complete design structure" /></p><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it! I hope this article helps you recreate beautiful UIs in .NET MAUI!</p><p>We built two account creation screens inspired by a Dribbble design. Along the way, we explored how to structure layouts with Grid, create overlapping effects, use gradients and customize the UI using Telerik UI for .NET MAUI RadBorder and DataForm.</p><p>As you can see, in just two screens we covered several tips that you can easily apply to your own applications.</p><p>I encourage you to keep exploring, experimenting and learning something new every day.  See you in the next article! &zwj;♀️</p><img src="https://feeds.telerik.com/link/23059/17476715.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:c0b3f88d-3c34-43f4-a479-4d674f54a82f</id>
    <title type="text">Replicating a Room Sublet App UI with .NET MAUI</title>
    <summary type="text">Let’s build out a design of a room subletting app using the Progress Telerik UI for .NET MAUI Rating control, plus concepts like overlapping effects and FormattedText.</summary>
    <published>2026-09-18T16:14:29Z</published>
    <updated>2026-10-16T23:38:55Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17466154/replicating-room-sublet-app-ui-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Let&rsquo;s build out a design of a room subletting app using the Progress Telerik UI for .NET MAUI Rating control, plus concepts like overlapping effects and FormattedText.</span></p><p>I dare say that a large percentage of young people, when they go to university, look for a room to rent where they can become independent and, of course, one that&rsquo;s close to their campus!</p><p>And how cool would it be if, during that special moment, an app could help us find the perfect place. And if there isn&rsquo;t an app that does it? Even better, let&rsquo;s learn how to create one!</p><p>That&rsquo;s exactly what we&rsquo;re going to do in this article. We&rsquo;re going to replicate a room sublet screen using .NET MAUI controls and one of my favorite Progress Telerik UI for .NET MAUI components: the <a target="_blank" href="https://www.telerik.com/maui-ui/rating">MAUI Rating control</a>. This UI was inspired from a <a target="_blank" href="https://dribbble.com/shots/11284577-Room-Rent-App-Concept">Dribbble design</a>. So get comfortable, and let&rsquo;s start building this UI that I absolutely love!! </p><h2 id="how-will-the-explanation-work">How Will the Explanation Work?</h2><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 one will be explained individually.</p><p>➖ <strong>Code explanation per block:</strong> In addition to the written explanation, each screen includes a set of blocks with the exact code snippets you need to implement and achieve the final 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 this design, we took inspiration from an original Dribbble UI, but made some adaptations and adjustments to align it with the goals of this article.</p><h3 id="-environment-setup"> Environment Setup</h3><p>You&rsquo;ll learn how to take advantage of some of the powerful Telerik UI for .NET MAUI components in this post. If you don&rsquo;t have the .NET MAUI library installed yet, visit the <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/quickstart">quick start page</a>, which explains step-by-step how to install Telerik UI for .NET MAUI, download the license key, configure the Telerik package source and install the Telerik MCP server (if needed).</p><h2 id="breaking-down-the-design">Breaking Down the Design</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://www.telerik.com/sfimages/default-source/blogs/2026/2026-09/01_room_structure.png?sfvrsn=7352a505_2" width="450" alt="Visual structure: 1. Header and background. 2. Description. 3. Footer" /></p><h2 id="header-and-background">1. Header and Background</h2><p>Woohoo!!  Let&rsquo;s start with the first block. I love this one because it contains several interesting components, but before adding them, we need to create the layout that will hold the entire page.</p><h3 id="grid">Grid</h3><p>We&rsquo;ll start with a grid composed of a single column. This will help us create the overlay effect between the background image and the main content.</p><p>Inside the grid, we&rsquo;ll place two elements:</p><ul><li>The background image.</li><li>Another Grid that will contain all the UI components we&rsquo;ll build throughout this article. This grid will have two columns and nine rows.</li></ul><p>In code, it should look something like this:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid ColumnDefinitions="*"&gt; 

    &lt;Image Grid.Column="0" Source="room.png" Aspect="AspectFill"/&gt;
 
    &lt;Grid ColumnDefinitions="*,auto" RowDefinitions="auto,auto,*,auto,auto,auto,auto,auto,auto" 
    RowSpacing="13"&gt; 
    
    &lt;!-- Add all the remaining components here -- &gt;
     
    &lt;/Grid&gt; 
&lt;/Grid
</code></pre><h3 id="name-and-result-label">Name and Result Label</h3><p>Now, inside the second grid, we&rsquo;ll add two Labels to display the room name and its result, as shown below:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Grid.Row="0" Grid.Column="0" Text="Roomlette" FontSize="32" FontAttributes="Bold" TextColor="White" Margin="20,40,0,0"/&gt; 

&lt;Label Grid.Row="1" Grid.Column="0" Text="Results: 1 / 31" FontSize="18" FontAttributes="Bold" TextColor="White" Margin="20,0,0,0"/&gt;
</code></pre><p>And then, let&rsquo;s add the three action buttons on the right side of the screen, as shown below:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button Grid.Row="0" Grid.Column="1" BackgroundColor="#0b0905" Opacity="0.8" HeightRequest="30" WidthRequest="30" CornerRadius="8" HorizontalOptions="Center" Margin="0,40,10,0" ImageSource="ellipsis.png"/&gt; 

&lt;Button Grid.Row="1" Grid.Column="1" BackgroundColor="#0b0905" Opacity="0.8" HeightRequest="30" WidthRequest="30" CornerRadius="8" HorizontalOptions="Center" Margin="0,10,10,0" ImageSource="stack.png"/&gt; 

&lt;Button Grid.Row="2" Grid.Column="1" BackgroundColor="#0b0905" Opacity="0.8" HeightRequest="30" WidthRequest="30" CornerRadius="8" HorizontalOptions="Center" Margin="0,10,10,0" ImageSource="save.png" VerticalOptions="Start"/&gt;
</code></pre><p>We&rsquo;ve finished building the first block! At this point, your result should look like this:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-09/02_room_header_and_background.png?sfvrsn=d71dfca0_2" width="450" alt="Room header and background block. Image of room, Roomlette Result 1 of 31" /></p><h2 id="description">2. Description</h2><p>For this second block, we&rsquo;ll add the elements that make up the main description of the screen. Let&rsquo;s see how to build them:</p><h3 id="main-description-and-location">Main Description and Location</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Grid.Row="3" Grid.Column="0" Text="Room for student,&amp;#10;fully furnished,,&amp;#10;close to the university." FontSize="23" FontAttributes="Bold" TextColor="White" Margin="20,40,0,0"/&gt;
 
&lt;Label Grid.Row="4" Grid.Column="0" Text="Malasa&ntilde;a, Madrid, Spain" FontSize="16" FontAttributes="Bold" TextColor="White" Margin="20,0,0,0"/&gt;
</code></pre><h3 id="price">Price</h3><p>Take a look at this Label. Even though it&rsquo;s a single label, it has different styles: one part has a different size, and another part is bold.</p><p>There are two ways to achieve this:</p><ol><li>Create a separate Label for each text style.</li><li>Use FormattedText, which allows us to apply different properties within the same Label.</li></ol><p>For this example, we&rsquo;ll use the second option. Here&rsquo;s how you can do it:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Grid.Row="5" Grid.Column="0" Margin="20,0,0,0"&gt; 
    &lt;Label.FormattedText&gt; 
    &lt;FormattedString&gt; 
    &lt;Span Text="&euro;950 / " FontSize="18" FontAttributes="Bold" TextColor="White"/&gt; 
    &lt;Span Text=" Month" FontSize="16" TextColor="White"/&gt; 
    &lt;/FormattedString&gt; 
    &lt;/Label.FormattedText&gt; 
&lt;/Label&gt;
</code></pre><h3 id="telerik-rating-control">Telerik Rating Control</h3><p>Oh yeah!, we&rsquo;ve reached my favorite part! This screen includes a Rating control, and we&rsquo;ll use the Telerik one. It&rsquo;s super easy to use, and we can play with the shape of the items, the colors for the selected and unselected items and many other things. </p><p>First, add the namespace:</p><pre class=" language-xml"><code class="prism  language-xml">xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"
</code></pre><p>And now, in your .xaml file, add the following code:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadShapeRating Grid.Row="6" Grid.Column="0" ItemFill="White" ItemStroke="#FFA500" AutomationId="radRating" Value="3" Margin="20,0,0,0"/&gt;
</code></pre><p>I also invite you to explore more about <a target="_blank" href="https://www.telerik.com/maui-ui/rating">Telerik Rating control in the official documentation</a>, which is really helpful!</p><h3 id="contact-button">Contact Button</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Button Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="2" Text="Contact" BackgroundColor="#af4544" FontSize="18" HeightRequest="25" HorizontalOptions="Fill" CornerRadius="10" Margin="20,0"/&gt;
</code></pre><p>We&rsquo;ve finished building the second block! At this point, your result should look like this:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-09/03_room_description.png?sfvrsn=99d5117c_2" width="450" alt="Room Description block with &#39;Room for student, fully furnished, close to the university. Malasana, Madrid, Spain. Price. Rating. Contact." /></p><h2 id="footer">3. Footer</h2><p>We&rsquo;re almost done! This footer block basically contains a <strong>Roulette</strong> button and three icons aligned horizontally at the end: <strong>Filter, Message</strong> and <strong>Save</strong>.</p><p>How does it look in code? Like this :</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button Grid.Row="8" Grid.Column="0" BackgroundColor="#0b0905" Padding="0" Text="Roulette" HeightRequest="18" WidthRequest="130" CornerRadius="8" Margin="20,10,20,20" ImageSource="roulette.png" HorizontalOptions="Start" /&gt;
 
&lt;HorizontalStackLayout Grid.Row="8" Grid.Column="1" Spacing="20" Margin="0,0,20,0"&gt; 
    &lt;Image Source="filtericon.png" HeightRequest="18" WidthRequest="18"/&gt; 
    &lt;Image Source="letter.png" HeightRequest="18" WidthRequest="18"/&gt; 
    &lt;Image Source="bookmark.png" HeightRequest="18" WidthRequest="18"/&gt; 
&lt;/HorizontalStackLayout&gt;
</code></pre><p>We&rsquo;ve finished building the third block! At this point, your result should look like this:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-09/04_room_footer.png?sfvrsn=e6cd0d16_2" width="450" alt="Room Footer block with roulette, filter. message, save" /></p><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s all! I hope this article helps you recreate beautiful UIs in .NET MAUI! </p><p>With a single screen, we explored several interesting concepts, such as using the Telerik UI for .NET MAUI Rating control, leveraging grid layouts to create overlapping effects, applying different styles within the same text using FormattedText and more!</p><p>I hope these techniques help you not only recreate this UI, but also inspire and support the interfaces you build from now on in .NET MAUI. </p><p>See you in the next article! &zwj;♀️</p><hr /><blockquote><p>If you want to explore Telerik UI for .NET MAUI, download your free trial today!</p><br /><p><a href="https://www.telerik.com/try/ui-for-maui" target="_blank" class="Btn">Try Now</a></p></blockquote><img src="https://feeds.telerik.com/link/23059/17466154.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:905a0827-91ae-4163-b112-3f31eb7c2249</id>
    <title type="text">Using the Camera in .NET MAUI with CameraView</title>
    <summary type="text">Learn how to use the .NET MAUI Community Toolkit CameraView control in your app, from initializing to creating the user interface.</summary>
    <published>2026-08-31T16:46:42Z</published>
    <updated>2026-10-16T23:38:55Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17435715/using-camera-net-maui-cameraview"/>
    <content type="text"><![CDATA[<p><span class="featured">Learn how to use the .NET MAUI Community Toolkit CameraView control in your app, from initializing to creating the user interface.</span></p><p>A functionality that is common in mobile applications is the ability to work with the camera. Although the .NET MAUI framework includes classes and methods to use the camera, having a component that allows creating interfaces that offer additional functionality helps speed up application development. That is why in this article, we will examine the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/views/camera-view">CameraView</a> control of the .NET MAUI Community Toolkit.</p><h2 id="what-is-the-cameraview-control">What Is the CameraView Control</h2><p>CameraView is a control within the <code>CommunityToolkit.Maui.Camera</code> package that helps perform tasks beyond taking photos and videos, allowing control of features such as flash, zoom, saving files and even hooks for reacting to different events.</p><p>This allows you to create experiences within your application without needing to navigate to an external application, giving you full control of the buttons, visual state and destination of captured files.</p><h2 id="using-the-cameraview-control-in-your-.net-maui-applications">Using the CameraView Control in Your .NET MAUI Applications</h2><p>Let&rsquo;s demonstrate the CameraView control&rsquo;s potential. To do this, in your project open the NuGet package manager and install the following packages:</p><pre class=" language-text"><code class="prism  language-text">CommunityToolkit.Maui.Camera
CommunityToolkit.Mvvm
</code></pre><p>The first package is the one we need to use the control and the APIs, while the second will allow using the MVVM pattern more easily in the project.</p><p>Once you have installed the camera control package, you will see a <code>ReadMe.txt</code> file with the steps to follow to correctly configure the control. This file tells us that we must go to <code>MauiProgram.cs</code>, adding the <code>UseMauiCommunityToolkitCamera</code> method for the purpose of initializing the control:</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>
        builder
            <span class="token punctuation">.</span><span class="token generic-method function">UseMauiApp<span class="token punctuation">&lt;</span>App<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 function">UseMauiCommunityToolkitCamera</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 control registered, we are ready to try it.</p><h2 id="declaring-permissions-per-platform">Declaring Permissions Per Platform</h2><p>Although the readme doesn&rsquo;t specify it, it is well known that to use hardware features on physical devices you must request permission from the user to use them. In our case, it is necessary to request permissions to use the camera and the microphone, which must be configured differently on each platform.</p><p>For Android, you should open the file <code>Platforms/Android/AndroidManifest.xml</code>, adding:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token prolog">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>manifest</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>android</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.android.com/apk/res/android<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>application</span> <span class="token attr-name"><span class="token namespace">android:</span>allowBackup</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"><span class="token namespace">android:</span>icon</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@mipmap/appicon<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>roundIcon</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@mipmap/appicon_round<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>supportsRtl</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>
...
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>uses-permission</span> <span class="token attr-name"><span class="token namespace">android:</span>name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>android.permission.CAMERA<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

    <span class="token comment">&lt;!--Optional. Only for video recording--&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>uses-permission</span> <span class="token attr-name"><span class="token namespace">android:</span>name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>android.permission.RECORD_AUDIO<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>manifest</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>For iOS, you should open the file <code>Platforms/iOS/Info.plist</code>, adding the following privacy descriptions:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token prolog">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span class="token doctype">&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>plist</span> <span class="token attr-name">version</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 punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dict</span><span class="token punctuation">&gt;</span></span>
    ...

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>key</span><span class="token punctuation">&gt;</span></span>NSCameraUsageDescription<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>key</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>string</span><span class="token punctuation">&gt;</span></span>PROVIDE YOUR REASON HERE<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>string</span><span class="token punctuation">&gt;</span></span>

    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>key</span><span class="token punctuation">&gt;</span></span>NSMicrophoneUsageDescription<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>key</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>string</span><span class="token punctuation">&gt;</span></span>PROVIDE YOUR REASON HERE<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>string</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dict</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>plist</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>For Windows no additional action is required.</p><h2 id="creating-a-viewmodel-to-manage-the-control">Creating a ViewModel to Manage the Control</h2><p>Once we&rsquo;ve configured the project to request permissions from the user, let&rsquo;s create the view model, which will allow managing the state of the control. For this, I created a class called <code>MainViewModel</code> with the following content.</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">string</span> statusMessage <span class="token operator">=</span> <span class="token string">"Grant permissions to start the camera."</span><span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">string</span> cameraName <span class="token operator">=</span> <span class="token string">"No camera selected"</span><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>HasPhoto<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
    <span class="token keyword">string</span><span class="token operator">?</span> lastPhotoPath<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">string</span><span class="token operator">?</span> lastVideoPath<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>RecordButtonText<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>RecordButtonColor<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
    <span class="token keyword">bool</span> isRecording<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">bool</span> isTorchOn<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">float</span> currentZoom <span class="token operator">=</span> <span class="token number">1.0f</span><span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">float</span> minimumZoom <span class="token operator">=</span> <span class="token number">1.0f</span><span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    <span class="token keyword">float</span> maximumZoom <span class="token operator">=</span> <span class="token number">4.0f</span><span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    CameraFlashMode selectedFlashMode <span class="token operator">=</span> CameraFlashMode<span class="token punctuation">.</span>Off<span class="token punctuation">;</span>

    <span class="token punctuation">[</span>ObservableProperty<span class="token punctuation">]</span>
    CameraInfo<span class="token operator">?</span> selectedCamera<span class="token punctuation">;</span>

    <span class="token keyword">public</span> IReadOnlyList<span class="token operator">&lt;</span>CameraFlashMode<span class="token operator">&gt;</span> FlashModes <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator">=</span> Enum<span class="token punctuation">.</span><span class="token generic-method function">GetValues<span class="token punctuation">&lt;</span>CameraFlashMode<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 keyword">public</span> <span class="token keyword">bool</span> HasPhoto <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">IsNullOrWhiteSpace</span><span class="token punctuation">(</span>LastPhotoPath<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">string</span> RecordButtonText <span class="token operator">=</span><span class="token operator">&gt;</span> IsRecording <span class="token operator">?</span> <span class="token string">"Stop video"</span> <span class="token punctuation">:</span> <span class="token string">"Record video"</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> Color RecordButtonColor <span class="token operator">=</span><span class="token operator">&gt;</span> IsRecording <span class="token operator">?</span> Colors<span class="token punctuation">.</span>Firebrick <span class="token punctuation">:</span> Colors<span class="token punctuation">.</span>DarkGreen<span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">UpdateCameraInfo</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>SelectedCamera <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            CameraName <span class="token operator">=</span> <span class="token string">"No camera selected"</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        CameraName <span class="token operator">=</span> $<span class="token string">"{SelectedCamera.Name} ({SelectedCamera.Position})"</span><span class="token punctuation">;</span>
        MinimumZoom <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">Max</span><span class="token punctuation">(</span><span class="token number">1.0f</span><span class="token punctuation">,</span> SelectedCamera<span class="token punctuation">.</span>MinimumZoomFactor<span class="token punctuation">)</span><span class="token punctuation">;</span>
        MaximumZoom <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">Max</span><span class="token punctuation">(</span>MinimumZoom<span class="token punctuation">,</span> SelectedCamera<span class="token punctuation">.</span>MaximumZoomFactor<span class="token punctuation">)</span><span class="token punctuation">;</span>
        CurrentZoom <span class="token operator">=</span> MinimumZoom<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">partial</span> <span class="token keyword">void</span> <span class="token function">OnSelectedCameraChanged</span><span class="token punctuation">(</span>CameraInfo<span class="token operator">?</span> <span class="token keyword">value</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token function">UpdateCameraInfo</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 code, I created some properties that can help us manage controls in the UI, for example:</p><ul><li><code>CameraName</code>: To indicate which camera is selected</li><li><code>LastPhotoPath</code> and <code>LastVideoPath</code>: To show the latest paths for photos and videos</li><li><code>IsRecording</code>: To maintain the recording state</li><li><code>CurrentZoom</code>, <code>MinimumZoom</code> and <code>MaximumZoom</code>: To control zoom values</li><li><code>OnSelectedCameraChanged(...)</code> and <code>UpdateCameraInfo()</code>: To update values when there is a camera change</li></ul><p>With the base viewmodel ready, it&rsquo;s time to create the graphical interface.</p><h2 id="creating-the-ui-for-the-application">Creating the UI for the Application</h2><p>It&rsquo;s time to create the graphical interface page for the application. We&rsquo;ll do this by creating a <code>ContentPage</code>, replacing the content with the following:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token prolog">&lt;?xml version="1.0" encoding="utf-8" ?&gt;</span>
<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>toolkit</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.microsoft.com/dotnet/2022/maui/toolkit<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 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">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 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>0<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">BackgroundColor</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 punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">toolkit:</span>CameraView</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>Camera<span class="token punctuation">"</span></span>
                    <span class="token attr-name">CameraFlashMode</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SelectedFlashMode}<span class="token punctuation">"</span></span>
                    <span class="token attr-name">IsTorchOn</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding IsTorchOn}<span class="token punctuation">"</span></span>
                    <span class="token attr-name">SelectedCamera</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding SelectedCamera}<span class="token punctuation">"</span></span>
                    <span class="token attr-name">ZoomFactor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding CurrentZoom}<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>12<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,6<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>#99000000<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">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>Start<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">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding CameraName}<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">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 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>ScrollView</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">MaximumHeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>360<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 attr-name">Spacing</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 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">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>CameraView media demo<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 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">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding StatusMessage}<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 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">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Take photo<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>OnTakePhotoClicked<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">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding RecordButtonText}<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>OnRecordVideoClicked<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 RecordButtonColor}<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 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 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 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">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Zoom<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>Slider</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">Minimum</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding MinimumZoom}<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Maximum</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding MaximumZoom}<span class="token punctuation">"</span></span>
                        <span class="token attr-name">Value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding CurrentZoom}<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.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">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Torch<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>Switch</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">IsToggled</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding IsTorchOn}<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 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.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">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Flash<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>Picker</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">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">ItemsSource</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding FlashModes}<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 SelectedFlashMode}<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>Image</span>
                    <span class="token attr-name">Source</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding LastPhotoPath}<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">IsVisible</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding HasPhoto}<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">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding LastPhotoPath}<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">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 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">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding LastVideoPath}<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">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 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>ScrollView</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>ContentPage</span><span class="token punctuation">&gt;</span></span>

</code></pre><p>In the previous code, we can highlight a few things:</p><ul><li>The namespace <code>xmlns:toolkit</code> is used so that the control can be used via <code>toolkit:CameraView</code>.</li><li>Properties such as <code>CameraFlashMode</code>, <code>IsTorchOn</code>, <code>SelectedCamera</code> and <code>ZoomFactor</code> are used, which will be connected to the viewmodel&rsquo;s properties.</li><li>We use events linked to the code behind <code>OnTakePhotoClicked</code> and <code>OnRecordVideoClicked</code>, because we work with capture APIs and streams.</li></ul><h2 id="connecting-the-content-page-with-the-viewmodel">Connecting the Content Page with the ViewModel</h2><p>Once we have created the XAML code for the graphical interface, it&rsquo;s time to connect it with the view model, as well as create the missing event handlers. To do this, replace the code behind of the XAML page with the following content:</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">readonly</span> MainViewModel viewModel <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Stream recordingStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span>Null<span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token function">MainPage</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>
        BindingContext <span class="token operator">=</span> viewModel<span class="token punctuation">;</span>

        Camera<span class="token punctuation">.</span>MediaCaptureFailed <span class="token operator">+</span><span class="token operator">=</span> OnMediaCaptureFailed<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">protected</span> <span class="token keyword">override</span> <span class="token keyword">async</span> <span class="token keyword">void</span> <span class="token function">OnAppearing</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">base</span><span class="token punctuation">.</span><span class="token function">OnAppearing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">await</span> <span class="token function">RequestCameraPermissions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">await</span> <span class="token function">LoadCameras</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">protected</span> <span class="token keyword">override</span> <span class="token keyword">void</span> <span class="token function">OnDisappearing</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">base</span><span class="token punctuation">.</span><span class="token function">OnDisappearing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Camera<span class="token punctuation">.</span>MediaCaptureFailed <span class="token operator">-</span><span class="token operator">=</span> OnMediaCaptureFailed<span class="token punctuation">;</span>
        recordingStream<span class="token punctuation">.</span><span class="token function">Dispose</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">RequestCameraPermissions</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">var</span> cameraStatus <span class="token operator">=</span> <span class="token keyword">await</span> Permissions<span class="token punctuation">.</span><span class="token generic-method function">RequestAsync<span class="token punctuation">&lt;</span>Permissions<span class="token punctuation">.</span>Camera<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 keyword">if</span> <span class="token punctuation">(</span>cameraStatus <span class="token keyword">is</span> not PermissionStatus<span class="token punctuation">.</span>Granted<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> <span class="token string">"You need to grant camera permission."</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">var</span> microphoneStatus <span class="token operator">=</span> <span class="token keyword">await</span> Permissions<span class="token punctuation">.</span><span class="token generic-method function">RequestAsync<span class="token punctuation">&lt;</span>Permissions<span class="token punctuation">.</span>Microphone<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 keyword">if</span> <span class="token punctuation">(</span>microphoneStatus <span class="token keyword">is</span> not PermissionStatus<span class="token punctuation">.</span>Granted<span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> <span class="token string">"You need to grant microphone permission to record video."</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">FileNotFoundException</span><span class="token punctuation">)</span> <span class="token function">when</span> <span class="token punctuation">(</span>OperatingSystem<span class="token punctuation">.</span><span class="token function">IsWindows</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> <span class="token string">"On unpackaged Windows apps, microphone permission may require a packaged app."</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">LoadCameras</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>
            <span class="token keyword">var</span> cameras <span class="token operator">=</span> <span class="token keyword">await</span> Camera<span class="token punctuation">.</span><span class="token function">GetAvailableCameras</span><span class="token punctuation">(</span>CancellationToken<span class="token punctuation">.</span>None<span class="token punctuation">)</span><span class="token punctuation">;</span>
            viewModel<span class="token punctuation">.</span>SelectedCamera <span class="token operator">=</span> cameras<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            viewModel<span class="token punctuation">.</span><span class="token function">UpdateCameraInfo</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">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>
            viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> $<span class="token string">"No cameras were found: {ex.Message}"</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">OnMediaCaptureFailed</span><span class="token punctuation">(</span><span class="token keyword">object</span><span class="token operator">?</span> sender<span class="token punctuation">,</span> MediaCaptureFailedEventArgs e<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> $<span class="token string">"Capture error: {e.FailureReason}"</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>In the previous code you can notice some interesting things:</p><ol><li>As indicated by the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/views/camera-view?tabs=android#request-permissions">CameraView documentation</a>, permissions must be requested manually from the user to use the camera and microphone, in addition to the per-platform configuration. We do this when the page starts through the method <code>RequestCameraPermissions()</code>.</li><li>It is possible to obtain the list of available cameras through <code>Camera.GetAvailableCameras</code>.</li><li>In case an error occurs, we use the event <code>OnMediaCaptureFailed</code> to handle it.</li></ol><p>This is just the beginning. Now, let&rsquo;s look at how to take a photo and a video.</p><h3 id="taking-a-photo-with-the-cameraview-control">Taking a Photo with the CameraView Control</h3><p>In the code-behind, we need a method that allows taking a photograph when pressing a button. To achieve this, we will do it through the following code:</p><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">OnTakePhotoClicked</span><span class="token punctuation">(</span><span class="token keyword">object</span><span class="token operator">?</span> sender<span class="token punctuation">,</span> EventArgs e<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">await</span> <span class="token keyword">using</span> <span class="token keyword">var</span> photoStream <span class="token operator">=</span> <span class="token keyword">await</span> Camera<span class="token punctuation">.</span><span class="token function">CaptureImage</span><span class="token punctuation">(</span>CancellationToken<span class="token punctuation">.</span>None<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">var</span> photoPath <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> $<span class="token string">"photo-{DateTime.Now:yyyyMMdd-HHmmss}.jpg"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">await</span> <span class="token keyword">using</span> <span class="token keyword">var</span> fileStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span>photoPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">await</span> photoStream<span class="token punctuation">.</span><span class="token function">CopyToAsync</span><span class="token punctuation">(</span>fileStream<span class="token punctuation">)</span><span class="token punctuation">;</span>

        viewModel<span class="token punctuation">.</span>LastPhotoPath <span class="token operator">=</span> photoPath<span class="token punctuation">;</span>
        viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> <span class="token string">"Photo saved successfully."</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>
        viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> $<span class="token string">"Unable to take photo: {ex.Message}"</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>In the previous method, we use <code>Camera.CaptureImage</code> to take a photograph, which returns a stream that we store locally. Next, we create a path using a safe location through <code>FileSystemAppDataDirectory</code>, which we use to save the stream with <code>File.Create</code> and <code>CopyToAsync</code>. Finally, we update the preview image and display the created path thanks to <code>LastPhotoPath</code> and <code>StatusMessage</code>.</p><h3 id="recording-a-video-with-cameraview">Recording a Video with CameraView</h3><p>To implement the recording process, we are going to create three methods. One controls the logic to know whether it is recording, starting or stopping the recording. The other two will allow starting and stopping the recording. The code looks as follows:</p><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">OnRecordVideoClicked</span><span class="token punctuation">(</span><span class="token keyword">object</span><span class="token operator">?</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>viewModel<span class="token punctuation">.</span>IsRecording<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">await</span> <span class="token function">StopRecording</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> <span class="token function">StartRecording</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">StartRecording</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>
        <span class="token keyword">var</span> videoPath <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> $<span class="token string">"video-{DateTime.Now:yyyyMMdd-HHmmss}.mp4"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        recordingStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span>videoPath<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">await</span> Camera<span class="token punctuation">.</span><span class="token function">StartVideoRecording</span><span class="token punctuation">(</span>recordingStream<span class="token punctuation">,</span> CancellationToken<span class="token punctuation">.</span>None<span class="token punctuation">)</span><span class="token punctuation">;</span>

        viewModel<span class="token punctuation">.</span>LastVideoPath <span class="token operator">=</span> videoPath<span class="token punctuation">;</span>
        viewModel<span class="token punctuation">.</span>IsRecording <span class="token operator">=</span> <span class="token keyword">true</span><span class="token punctuation">;</span>
        viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> <span class="token string">"Recording video..."</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> recordingStream<span class="token punctuation">.</span><span class="token function">DisposeAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        recordingStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span>Null<span class="token punctuation">;</span>
        viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> $<span class="token string">"Unable to start video recording: {ex.Message}"</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">StopRecording</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>
        <span class="token keyword">await</span> Camera<span class="token punctuation">.</span><span class="token function">StopVideoRecording</span><span class="token punctuation">(</span>CancellationToken<span class="token punctuation">.</span>None<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">await</span> recordingStream<span class="token punctuation">.</span><span class="token function">DisposeAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        recordingStream <span class="token operator">=</span> Stream<span class="token punctuation">.</span>Null<span class="token punctuation">;</span>
        viewModel<span class="token punctuation">.</span>IsRecording <span class="token operator">=</span> <span class="token keyword">false</span><span class="token punctuation">;</span>
        viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> <span class="token string">"Video saved successfully."</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>
        viewModel<span class="token punctuation">.</span>StatusMessage <span class="token operator">=</span> $<span class="token string">"Unable to stop video recording: {ex.Message}"</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>In the previous code, the methods do the following:</p><ul><li><code>OnRecordVideoClicked(...)</code>: Through the property <code>IsRecording</code>, it determines which method should be invoked when the user presses the button in the UI.</li><li><code>StartVideoRecording()</code>: It obtains a path using the current time to name the file and creates a stream at that location. Then, it uses the method <code>Camera.StartVideoRecording</code> to start the recording. It is important to keep the stream open while the recording is active.</li><li><code>StopRecording</code>: This ends the capture using <code>Camera.StopVideoRecording</code>. After stopping the recording, the stream is closed to release the file.</li></ul><h3 id="testing-the-application">Testing the Application</h3><p>After adding all the previous code to the application, it&rsquo;s time to test the functionality. When running the application, we get the following result:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/camera-view-live-preview.gif?sfvrsn=a9f799b0_2" alt="CameraView showing a live camera preview on screen" /></p><p>You can see that all features work correctly, and that it&rsquo;s possible to take photos and videos within the same application.</p><h2 id="conclusion">Conclusion</h2><p>In this article you have learned about the CameraView control from the Community Toolkit, and how to integrate it into your own .NET MAUI applications. We went step by step to initialize it, configure permissions, create the view model and the user interface. With what you&rsquo;ve learned, you can now create your own experiences using the control in more complex scenarios.</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">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/17435715.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:11e0f437-8d92-4dc9-a2b6-a4030526b9ad</id>
    <title type="text">Skeleton in .NET MAUI: What It Is and How to Use It</title>
    <summary type="text">A skeleton allows us to indicate to users that an app or page is loading. This improves the user experience, providing feedback that the app isn’t broken.</summary>
    <published>2026-08-24T15:23:04Z</published>
    <updated>2026-10-16T23:38:55Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17427494/skeleton-net-maui-what-and-how-to-use-it"/>
    <content type="text"><![CDATA[<p><span class="featured">A skeleton allows us to indicate to users that an app or page is loading. This improves the user experience, providing feedback that the app isn&rsquo;t broken.</span></p><p>Let&rsquo;s face it: as users, we tend to be impatient when an application doesn&rsquo;t respond quickly. It&rsquo;s very easy to assume that the app has frozen or isn&rsquo;t working when it doesn&rsquo;t give us any kind of feedback.</p><p>Imagine you have an application with a menu that displays a list connected to a backend. If the backend takes time to respond and we don&rsquo;t indicate to the user that data is loading, they will most likely think: &ldquo;This app doesn&rsquo;t work.&rdquo;</p><p>As developers, it&rsquo;s important to prevent this from happening. There are different ways to visually communicate that data is loading, and one of my favorites is using skeletons. These allow us to gently indicate to the user that the app is performing an action, even if the content isn&rsquo;t ready yet.</p><p>In this article, we&rsquo;ll learn what a Skeleton is, in which scenarios it is most useful, and how to implement the Skeleton component designed by Progress Telerik UI for .NET MAUI.</p><h2 id="what-is-a-skeleton">What Is a Skeleton?</h2><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/00_skeleton_sample.png?sfvrsn=b89cf7f6_2" alt="Skeleton sample" /><br /><span style="font-size:11px;">Image generated using AI for illustrative purposes</span></p><p>A skeleton is a visual element used to indicate that content is loading. Basically, it appears on the screen as blocks (usually gray) placed in the same positions where the actual elements will be displayed once the data is available and the effect disappears.</p><p>Its purpose is to give users context while the information is loading by showing the structure that the content will have. It also typically includes a subtle animation that communicates the app is still working, even if all that&rsquo;s visible are gray blocks or rectangles.</p><p>This way, instead of showing empty spaces, a traditional loader or, even worse, nothing at all, a skeleton keeps the interface clear and lets the user know that the application is working fine.</p><h2 id="✅-when-should-you-use-skeletons">✅ When Should You Use Skeletons?</h2><p>It&rsquo;s important to see skeletons not just as a visual element to &ldquo;entertain&rdquo; users, but as a tool that allows your app to handle loading states in a smoother and more intentional way.</p><p>Let&rsquo;s look at some scenarios where skeletons are especially useful:</p><h3 id="when-waiting-for-api-responses">When Waiting for API Responses</h3><p>No matter how optimized your app is, it still depends on backend response times. Skeletons help bridge that gap by showing structure while data is loading. Ideally, you should display the skeleton only while the request is in progress and replace it immediately once the data is available.</p><h3 id="screens-with-heavy-images">Screens with Heavy Images</h3><p>When loading images that may take time, skeletons are extremely useful to indicate that content is coming, instead of leaving empty or broken-looking spaces.</p><h2 id="❌-when-are-skeletons-not-recommended">❌ When Are Skeletons NOT Recommended?</h2><h3 id="when-data-is-not-actually-loading">When Data Is Not Actually Loading</h3><p>Avoid using skeletons just for visual purposes. If there&rsquo;s no real loading happening, then you don&rsquo;t need them.</p><h3 id="for-instant-loads">For Instant Loads</h3><p>If the content appears immediately, adding a skeleton only adds unnecessary complexity and can even hurt the experience.</p><h3 id="very-simple-screens">Very Simple Screens</h3><p>On screens with minimal content, a skeleton might be overkill. A simple layout or even a simple loading indicator could be enough.</p><h2 id="meet-the-telerik-skeleton-">Meet the Telerik Skeleton </h2><p>Did you know that Progress Telerik provides a <strong><a href="https://www.telerik.com/maui-ui/skeleton">Skeleton component for .NET MAUI</a></strong>? Oh yeahh! </p><p>Now that you&rsquo;ve seen how powerful using one can be, let&rsquo;s quickly go through how to implement it and highlight some of its most important benefits.</p><p>Before we dive in, let&rsquo;s make sure your environment is ready. Just keep these two key points in mind:</p><ul><li><strong>Create a Telerik account</strong>: If you don&rsquo;t have a <a href="https://www.telerik.com/account/">Telerik account</a> yet, you can create one for free. You&rsquo;ll get access to a trial license that allows you to explore not only the Skeleton component, but the full set of UI controls available for .NET MAUI.</li><li><strong>Install Telerik UI for .NET MAUI</strong>: This is a one-time setup, so you won&rsquo;t need to repeat it for each component. If you haven&rsquo;t installed it yet, I&rsquo;ve included an article that walks you through the process step by step for both <a href="https://www.telerik.com/maui-ui/documentation/get-started/first-steps-vs">Visual Studio</a> and <a href="https://www.telerik.com/maui-ui/documentation/get-started/first-steps-vs-code">Visual Studio Code</a>.</li></ul><h3 id="adding-the-namespace">Adding the Namespace</h3><pre><code>xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"
</code></pre><h3 id="registering-the-component">Registering the Component</h3><p>Go to your <strong>MauiProgram.cs</strong> file and, inside the CreateMauiApp method, register the Telerik controls using the <strong>UseTelerik()</strong> extension method.</p><pre class=" language-csharp"><code class="prism  language-csharp">using Telerik.Maui.Controls.Compatibility;
public static class MauiProgram
{

    public static MauiApp CreateMauiApp()
    {
    var builder = MauiApp.CreateBuilder();
    builder
    .UseTelerik()
    .UseMauiApp&lt;App&gt;()
    .ConfigureFonts(fonts =&gt;
    {
    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
    });
    return builder.Build();
    
    }
}
</code></pre><h3 id="how-to-use-it">How to Use It?</h3><p>Using it is very simple. You just have to add a tag like the following:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadSkeleton x:Name="skeleton"/&gt;
</code></pre><h3 id="skeleton-types-in-the-telerik-ui-for-.net-maui-library">Skeleton Types in the Telerik UI for .NET MAUI Library</h3><p>Typically, when creating a skeleton, you need to build the structure from scratch. However, the Telerik UI for .NET MAUI Skeleton component comes with predefined structures (anatomies), which helps you save both time and code. (Honestly, this is gold. A huge win!)</p><p>This control offers several built-in structures that you can use to represent different types of content:</p><p>➖ <strong>Article:</strong> Displays a layout with a small image placeholder on the left and multiple text lines on the right, simulating a title and description.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/01_article_skeleton_type.png?sfvrsn=62c04b72_2" alt="Article skeleton sample" /></p><p>➖ <strong>Text:</strong> A simple text structure composed of multiple lines, typically used to represent titles and paragraphs.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/02_text_skeleton_type.png?sfvrsn=844034a1_2" alt="Text skeleton sample" /></p><p>➖ <strong>PersonalCircle:</strong> Shows a circular avatar placeholder with text lines next to it, commonly used for user profiles or list items with avatars.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/03_personalcircle_skeleton_type.png?sfvrsn=72d71c48_2" alt="Personal circle skeleton sample" /></p><p>➖ <strong>PersonaSquare:</strong> Similar to PersonaCircle, but uses a square (with rounded corners) instead of a circular avatar.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/04_personasquare_skeleton_type.png?sfvrsn=7d7748ae_2" alt="Personal square skeleton sample" /></p><p>➖ <strong>Image:</strong> Represents a large media placeholder with a single text line below, ideal for image-focused layouts.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/05_image_skeleton_type.png?sfvrsn=2bd148cc_2" alt="Personal square skeleton sample" /></p><p>➖ <strong>Video:</strong> Simulates a video layout with a small avatar and text at the top, followed by a large media area and additional text lines below.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/06_video_skeleton_type.png?sfvrsn=dae0aadc_2" alt="Video skeleton sample" /></p><p>➖ <strong>Card:</strong> Displays a card-style layout with a title at the top, a large image placeholder and text lines at the bottom.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/07_card_skeleton_type.png?sfvrsn=5d4d50e4_2" alt="Card skeleton sample" /></p><p>➖ <strong>ContentFeed:</strong> Mimics a feed-style layout with a header (avatar + one line), a large content block and text lines below, similar to social media posts.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/08_contentfeed_skeleton_type.png?sfvrsn=222eb4d7_2" alt="Content feed sample" /><br /><span style="font-size:11px;">The images of the Skeleton types were generated using AI for better understanding</span></p><p>To use any of these types, you just need to use the SkeletonType property as shown below:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadSkeleton SkeletonType="Article" /&gt;
</code></pre><h2 id="-custom-skeleton-view"> Custom Skeleton View</h2><p>But &hellip; what if you want to create your own skeleton anatomy? </p><p>You can do that too!  Although the predefined types help you save time and effort, they don&rsquo;t always fit your design. That&rsquo;s why Progress Telerik allows you to create a fully custom one.</p><p>The idea is very simple: you define your own layout (just like your real UI, but without data) and assign it to the <strong>RadSkeleton</strong> using the LoadingViewTemplate property.</p><h3 id="️-implementation">️ Implementation</h3><p>First, define your RadSkeleton and assign a custom template to it:</p><pre class=" language-xml"><code class="prism  language-xml">    &lt;telerik:RadSkeleton LoadingViewTemplate="{StaticResource CustomSkeletonView}"  
    Grid.Row="1" 
    x:Name="skeleton"&gt; 
    
    &lt;!-- Your real content goes here --&gt;
    
    &lt;/telerik:RadSkeleton&gt;
</code></pre><p>Then, create the DataTemplate that will represent your skeleton:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;DataTemplate x:Key="CustomSkeletonView"&gt;
&lt;Grid RowDefinitions="40, 100, 200"
RowSpacing="10"
Padding="10"&gt;

    &lt;HorizontalStackLayout Spacing="10"&gt;
    &lt;BoxView WidthRequest="40" HeightRequest="40" CornerRadius="20"/&gt;
    &lt;BoxView WidthRequest="40" HeightRequest="40" CornerRadius="20"/&gt;
    &lt;BoxView WidthRequest="40" HeightRequest="40" CornerRadius="20"/&gt;
    &lt;BoxView WidthRequest="40" HeightRequest="40" CornerRadius="20"/&gt;
    &lt;/HorizontalStackLayout&gt;
    &lt;BoxView WidthRequest="200"
    HeightRequest="100"
    HorizontalOptions="Start"
    Grid.Row="1"
    CornerRadius="12"/&gt;
    
    &lt;Grid Grid.Row="2"
    ColumnDefinitions="40, *"
    ColumnSpacing="10"&gt;
    &lt;BoxView HeightRequest="40"
    WidthRequest="40"
    CornerRadius="20"
    Grid.Column="0"/&gt;
    
    &lt;VerticalStackLayout Spacing="10" Grid.Column="1"&gt;
    &lt;BoxView HeightRequest="20" WidthRequest="120" CornerRadius="6"/&gt;
    &lt;BoxView HeightRequest="20" WidthRequest="180" CornerRadius="6"/&gt;
    &lt;/VerticalStackLayout&gt;
    &lt;/Grid&gt;
&lt;/Grid&gt;
&lt;/DataTemplate&gt;
</code></pre><p>Done!!! We made it!  Did you like it?</p><h2 id="conclusion">Conclusion</h2><p>I hope this article helped you understand what a skeleton is and how it can improve the user experience in your .NET MAUI applications. </p><p>From understanding when to use it, to exploring the different types provided by Progress Telerik and finally implementing it in your UI, you&rsquo;re now ready to apply this knowledge in your own apps. I invite you to explore more about the Telerik Skeleton for .NET MAUI in the following articles:</p><ul><li><a href="https://www.telerik.com/maui-ui/skeleton">https://www.telerik.com/maui-ui/skeleton</a></li><li><a href="https://www.telerik.com/maui-ui/documentation/controls/skeleton/overview">https://www.telerik.com/maui-ui/documentation/controls/skeleton/overview</a></li></ul><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><h3>Ready to Try Telerik UI for .NET MAUI?</h3><p>Give the Skeleton component plus <a target="_blank" href="https://www.telerik.com/maui-ui">70 other .NET MAUI components</a> a try, free for 30 days.</p><p><a href="https://www.telerik.com/try/ui-for-maui" target="_blank" class="Btn">Try Telerik UI for .NET MAUI</a></p><img src="https://feeds.telerik.com/link/23059/17427494.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:0cad5621-adf3-4d3d-b318-ced20113c4f5</id>
    <title type="text">Building an Onboarding and Registration UI in .NET MAUI</title>
    <summary type="text">See how to use LinearGradientBrush and RadialGradientBrush, structure grid layouts and create a dynamic form using the Telerik DataForm in .NET MAUI.</summary>
    <published>2026-08-10T18:11:16Z</published>
    <updated>2026-10-16T23:38:55Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17411672/building-onboarding-registration-ui-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">See how to use LinearGradientBrush and RadialGradientBrush, structure grid layouts and create a dynamic form using the Telerik DataForm in .NET MAUI.</span></p><p>Have you ever seen apps with super fresh screens with gradients that make you think: &ldquo;OMG, where do I get that image to use as a background in my apps?&rdquo; </p><p>Well, today you won&rsquo;t just see a UI like that &hellip; you&rsquo;ll learn how to create it from scratch. This UI is inspired by a design from <a target="_blank" href="https://dribbble.com/shots/22753453-Sign-In-Sign-Up-Form-Mobile-App">Dribbble</a>, and we&rsquo;ll recreate it step by step.</p><p>Here&rsquo;s where it gets interesting: we&rsquo;ll build that super modern gradient using <code>LinearGradientBrush</code> in .NET MAUI, without relying on external images, achieving that clean look directly from code.</p><p>From there, we&rsquo;ll put together the entire experience: an onboarding screen with a clean and modern design, along with a registration form using the Progress Telerik UI for <a target="_blank" href="https://www.telerik.com/maui-ui/dataform">.NET MAUI DataForm</a>.</p><p>The best part is that you&rsquo;ll understand every step of the process, from the background gradient to the structure of the form and how to use the components, so you can easily adapt it to your own projects.</p><p>So let&rsquo;s get started, and you&rsquo;ll see how simple and fast it&rsquo;s to build a UI like this. </p><h2 id="how-will-the-explanation-work">How Will the Explanation Work?</h2><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 screens, each identified with a name and a color. Each one will be explained individually.</p><p>➖ <strong>Code explanation per block:</strong> In addition to the written explanation, each screen includes a set of blocks with the exact code snippets you need to implement and achieve the final 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 this design, we took inspiration from an original Dribbble UI, but made some adaptations and adjustments to align it with the goals of this article.</p><h2 id="-environment-setup"> Environment Setup</h2><p>You&rsquo;ll learn how to take advantage of some of the powerful Telerik UI for .NET MAUI components in this post. If you don&rsquo;t have the .NET MAUI library installed yet, visit the <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/quickstart">quick start page</a>, which explains step-by-step how to install Telerik UI for .NET MAUI, download the license key, configure the Telerik package source and install the Telerik MCP server (if needed).</p><h2 id="breaking-down-the-design">Breaking Down the Design</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 sf-image-responsive="true" src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/01_visual_structure.png?sfvrsn=9e86635b_2" title="01_visual_structure" alt="Visual structure of 1. Onboarding and 2. Signup" sf-size="362110" /></p><h2 id="onboarding">1. Onboarding</h2><p>Oh yeahh! We&rsquo;ve reached the first screen!  This is an onboarding screen, and I really like it because it&rsquo;s perfect for practicing XAML while building a modern UI.</p><p>One of the highlights here is the gradient background. When we see something like this, it&rsquo;s easy to think we need an image to achieve it, but that&rsquo;s not the case. We&rsquo;ll build it from scratch using <code>LinearGradientBrush</code> from .NET MAUI, giving you full control to customize and experiment with gradients directly from code, without relying on external assets.</p><p>On top of that, this screen helps us structure a real layout by combining key UI elements: a centered image, a title with a description, and simple actions like a button and a &ldquo;Skip&rdquo; option.</p><h3 id="adding-the-gradient">Adding the Gradient</h3><p>To get started with the code, the first thing we&rsquo;ll create is the gradient that will be used as the background for the entire page. We&rsquo;ll assign it directly as the background of the <code>ContentPage</code>.</p><p>Using <code>LinearGradientBrush</code>, add the following code block right before defining the main layout. Keep in mind that you can tweak each variation of the gradient using <code>GradientStop</code>.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;?xml version="1.0" encoding="utf-8" ?&gt; 
&lt;ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
x:Class="TicketSampleApp.Pages.FormsUI.FormIntroPage" 
Title="FormIntroPage"&gt; 
&lt;ContentPage.Background&gt; 
    &lt;LinearGradientBrush StartPoint="0,0" EndPoint="0.8,1"&gt; 
    &lt;GradientStop Color="#FFCFE8" Offset="0.00" /&gt; 
    &lt;GradientStop Color="#F7D5F3" Offset="0.28" /&gt; 
    &lt;GradientStop Color="#ECE1FF" Offset="0.55" /&gt; 
    &lt;GradientStop Color="#DDF0FF" Offset="0.82" /&gt; 
    &lt;GradientStop Color="#F7FCFF" Offset="1.00" /&gt; 
    &lt;/LinearGradientBrush&gt; 
    &lt;/ContentPage.Background&gt;
 
&lt;!-- Add your Grid here --&gt;
 
&lt;/ContentPage&gt;
</code></pre><p>✍️ If you want to learn more about <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/user-interface/brushes/lineargradient?view=net-maui-10.0">LinearGradientBrush, I recommend checking out the MS Learn article</a>.</p><h3 id="main-layout">Main Layout</h3><p>Now let&rsquo;s continue with one of the most important components in a .xaml file: the main layout. For this screen, we&rsquo;ll add a <strong>Grid</strong> with two columns and five rows:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid 
    Padding="24" 
    RowDefinitions="420,Auto,Auto,*,Auto" 
    ColumnDefinitions="*,Auto"&gt; 
    &lt;!-- Add the remaining code here --&gt;  
&lt;/Grid&gt;
</code></pre><p>Keep in mind that this <strong>Grid</strong> will contain all the elements of your page, so it should be placed inside the <strong>ContentPage</strong>, exactly where the previous code block says: &ldquo;Add your Grid here.&rdquo;</p><h3 id="the-halo">The Halo</h3><p>As you may notice, the main image has a kind of &ldquo;halo&rdquo; behind it, almost like a soft circle. In this case, we enhanced that effect using a <strong>RadialGradientBrush</strong>. </p><p>This code block should be placed right at the beginning of the <strong>Grid</strong>, before adding the image and the rest of the elements.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;!-- Halo --&gt; 
&lt;Ellipse 
    Grid.Row="0" 
    Grid.ColumnSpan="2" 
    WidthRequest="340" 
    HeightRequest="340" 
    HorizontalOptions="Center" 
    VerticalOptions="Center" 
    Opacity="0.65" 
    Margin="0,-40,0,0"&gt; 
    &lt;Ellipse.Fill&gt; 
    &lt;RadialGradientBrush Center="0.5,0.32" Radius="0.75"&gt; 
    &lt;GradientStop Color="#FFFFFF" Offset="0.0" /&gt; 
    &lt;GradientStop Color="#FFFFFF" Offset="0.2" /&gt; 
    &lt;GradientStop Color="#FFF6FB" Offset="0.4" /&gt; 
    &lt;GradientStop Color="#F3E3F8" Offset="0.65" /&gt; 
    &lt;GradientStop Color="Transparent" Offset="1.0" /&gt; 
    &lt;/RadialGradientBrush&gt; 
    &lt;/Ellipse.Fill&gt; 
&lt;/Ellipse&gt;
</code></pre><p>✍️ If you want to learn more about <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/maui/user-interface/brushes/radialgradient?view=net-maui-10.0">RadialGradientBrush, check out the MS Learn article</a>.</p><h3 id="main-images-labels-and-button">Main Images, Labels and Button</h3><p>Now we&rsquo;ll continue by adding the remaining elements of the screen: the main image, labels and the button.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;!-- Image --&gt; 
&lt;Image 
    Grid.Row="0" 
    Grid.ColumnSpan="2" 
    Source="onboarding_cartoon" 
    HeightRequest="450" 
    Aspect="AspectFit" 
    HorizontalOptions="Center" 
    VerticalOptions="Center" /&gt;
 
&lt;!-- Title --&gt; 
&lt;Label 
    Grid.Row="1" 
    Grid.ColumnSpan="2" 
    Text="Get Detailed Analytics" 
    FontSize="24" 
    FontAttributes="Bold" 
    TextColor="#111111" 
    Margin="0,20,0,0" /&gt;
 
&lt;!-- Description --&gt; 
&lt;Label 
    Grid.Row="2" 
    Grid.ColumnSpan="2" 
    Text="Complete the quiz to get a detailed report&amp;#10;of your performance and challenge&amp;#10;yourself to achieve more." 
    FontSize="14" 
    FontAttributes="Bold" 
    TextColor="#333333" 
    LineHeight="1.3" 
    Margin="0,24,0,0" /&gt;
     
&lt;!-- Skip --&gt; 
&lt;Label 
    Grid.Row="4" 
    Grid.Column="0"  
    Text="Skip" 
    FontAttributes="Bold" 
    FontSize="15" 
    VerticalOptions="Center" 
    HorizontalOptions="Start" /&gt; 

&lt;!-- Button --&gt; 
&lt;Button 
    Grid.Row="4" 
    Grid.Column="1" 
    Text="Next" 
    FontSize="17" 
    FontAttributes="Bold" 
    TextColor="White" 
    BackgroundColor="#111111" 
    CornerRadius="10" 
    Padding="35,14" 
    HorizontalOptions="End" /&gt;
</code></pre><p>Once the layout and components are in place, the result should look like this:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/02_onboarding_page.png?sfvrsn=cbc8612c_2" alt="1. Onboarding Page" /></p><h2 id="sign-up">2. Sign Up</h2><p>For our second screen, we&rsquo;ll also add a gradient. As you can see, it&rsquo;s not exactly the same as the one on the previous screen, so we&rsquo;ll create a new one with different color variations, applying it in the same way we did before, directly in the <strong>ContentPage.</strong></p><pre class=" language-xml"><code class="prism  language-xml">&lt;ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TicketSampleApp.Pages.FormsUI.SignUpPage"
xmlns:telerik="clr-namespace:Telerik.Maui.Controls;assembly=Telerik.Maui.Controls"
Title="SignUpPage"&gt; 
    &lt;ContentPage.Background&gt; 
    &lt;LinearGradientBrush StartPoint="0,0" EndPoint="1,1"&gt; 
    &lt;GradientStop Color="#F8F7FF" Offset="0.00" /&gt; 
    &lt;GradientStop Color="#FFFFFF" Offset="0.28" /&gt; 
    &lt;GradientStop Color="#F9FBFF" Offset="0.50" /&gt; 
    &lt;GradientStop Color="#EAF7FF" Offset="0.72" /&gt; 
    &lt;GradientStop Color="#F8DDF2" Offset="1.00" /&gt; 
    &lt;/LinearGradientBrush&gt; 
    &lt;/ContentPage.Background&gt; 

&lt;!-- Add your Grid here --&gt;  

&lt;/ContentPage&gt;
</code></pre><h3 id="main-layout-of-sign-up">Main Layout of Sign Up</h3><p>Just like in the previous page, we&rsquo;ll use a Grid. In this case, it will have eight rows and two columns. Inside this <strong>Grid</strong>, we&rsquo;ll add all the remaining elements.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid 
    Padding="26" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto" 
    ColumnDefinitions="*,*" 
    ColumnSpacing="12" 
    VerticalOptions="Center" 
    RowSpacing="18"&gt; 

    &lt;!-- Add the remaining code here --&gt; 

&lt;/Grid&gt;
</code></pre><h3 id="title--description">Title &amp; Description</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Label 
Grid.Row="0" 
Grid.ColumnSpan="2" 
Text="Sign Up" 
FontSize="24" 
FontAttributes="Bold" /&gt;
 
&lt;Label 
Grid.Row="1" 
Grid.ColumnSpan="2" 
Text="Just a few quick things to get started" 
FontSize="14" /&gt;
</code></pre><h2 id="lets-add-the-form">Let&rsquo;s Add the Form!</h2><p>One of my favorite moments has arrived  (because yes, I absolutely love this component). For our form, we&rsquo;ll use the <strong>Telerik UI for .NET MAUI DataForm</strong>!</p><p>To use it, don&rsquo;t forget to follow the instructions in the <strong>&ldquo; Environment Setup&rdquo;</strong> section explained earlier. Additionally, you&rsquo;ll just need to add the following namespace to your XAML:</p><pre class=" language-xml"><code class="prism  language-xml">xmlns:telerik="clr-namespace:Telerik.Maui.Controls;assembly=Telerik.Maui.Controls"
</code></pre><h3 id="creating-the-model">Creating the Model</h3><p>To display the fields in our form, we&rsquo;ll create a model where we define everything we need, such as the email and password. This is also where we specify whether each field is required, its display name and the data type.</p><p>The data type is especially important, for example, for password fields. It masks the input, showing <code>***</code> as you type.</p><p>Additionally, the Telerik DataForm uses these attributes to automatically generate and validate the UI, which means we don&rsquo;t need to manually create each input field or handle basic validation logic.</p><p>Our model should look like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">public class SignUp : NotifyPropertyChangedBase
{ 
    private string email; 
    private string password; 
    private string confirmPassword;
     
    [Required] 
    [Display(Name = "Email ID")] 
    public string Email 
    { 
    get =&gt; email; 
    set =&gt; UpdateValue(ref email, value); 
    }
     
    [Required] 
    [Display(Name = "New Password")] 
    [DataType(DataType.Password)]
     
    public string Password 
    { 
    get =&gt; password;  
    set =&gt; UpdateValue(ref password, value); 
    }
     
    [Required] 
    [Display(Name = "Confirm Password")] 
    [DataType(DataType.Password)]
     
    public string ConfirmPassword 
    { 
    get =&gt; confirmPassword; 
    set =&gt; UpdateValue(ref confirmPassword, value); 
    } 
}
</code></pre><p>Now, go to your XAML page and set the <code>BindingContext</code> from the code-behind. For this article, we&rsquo;ll keep the example simple and assign a new instance of our SignUp model directly in the page constructor:</p><pre class=" language-csharp"><code class="prism  language-csharp">public SignUpPage() 
{ 
    InitializeComponent(); 
    this.BindingContext = new Models.SignUp(); 
}
</code></pre><p>This allows the DataForm to read the model properties and generate the corresponding fields based on the attributes we defined earlier.</p><h3 id="adding-it-in-xaml">Adding It in XAML</h3><p>Finally, we can add it to our XAML. Simply include something like the following:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadDataForm 
    Grid.Row="2" 
    Grid.ColumnSpan="2" 
    x:Name="dataForm" 
    AutomationId="dataForm" /&gt;
</code></pre><p>At this point, the DataForm will automatically generate the form fields based on the model we defined earlier.</p><h3 id="terms--conditions-and-button">Terms &amp; Conditions and Button</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;CheckBox 
Grid.Row="3" 
Grid.Column="0" 
IsChecked="True" 
Color="#8A2BFF" 
HorizontalOptions="Start" 
VerticalOptions="Center" /&gt;
 
&lt;Label 
Grid.Row="3" 
Grid.ColumnSpan="2" 
Text="I Agree With The Terms And Conditions" 
FontSize="12" 
VerticalOptions="Center" 
Margin="28,0,0,0" /&gt; 

&lt;Button 
Grid.Row="4" 
Grid.ColumnSpan="2" 
Text="Sign Up" 
FontSize="16" 
FontAttributes="Bold" 
TextColor="White" 
BackgroundColor="#111111" 
CornerRadius="6"  
HeightRequest="52" /&gt;
</code></pre><h3 id="social-networks">Social Networks</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;HorizontalStackLayout 
Grid.Row="5" 
Grid.ColumnSpan="2" 
Spacing="12" 
HorizontalOptions="Center" 
VerticalOptions="Center"&gt; 

    &lt;BoxView 
    HeightRequest="1" 
    WidthRequest="95" 
    Color="#D8D8D8" 
    VerticalOptions="Center" /&gt;
     
    &lt;Label 
    Text="Or with" 
    FontSize="12" 
    VerticalOptions="Center" /&gt;
     
    &lt;BoxView 
    HeightRequest="1" 
    WidthRequest="95" 
    Color="#D8D8D8" 
    VerticalOptions="Center" /&gt; 
    
&lt;/HorizontalStackLayout&gt; 

&lt;Button 
Grid.Row="6" 
Grid.Column="0" 
Text="Facebook" 
FontSize="12" 
TextColor="#111111" 
BackgroundColor="White" 
BorderColor="#DDDDDD" 
BorderWidth="1" 
CornerRadius="8" 
HeightRequest="48" 
ImageSource="facebook.png" 
ContentLayout="Left,10" /&gt; 

&lt;Button 
Grid.Row="6" 
Grid.Column="1" 
Text="Google" 
FontSize="12" 
TextColor="#111111" 
BackgroundColor="White" 
BorderColor="#DDDDDD" 
BorderWidth="1"  
CornerRadius="8" 
HeightRequest="48" 
ImageSource="google.png" 
ContentLayout="Left,10" /&gt;
 
&lt;Label 
Grid.Row="7" 
Grid.Column="0" 
Text="Already have an account?" 
FontSize="12" 
TextColor="#777777" 
HorizontalOptions="End" /&gt; 

&lt;Label 
Grid.Row="7" 
Grid.Column="1" 
Text="Sign In" 
FontSize="12" 
FontAttributes="Bold" 
TextColor="#111111" 
TextDecorations="Underline" 
HorizontalOptions="Start" 
Margin="4,0,0,0" /&gt;
</code></pre><p>Once the layout and components are in place, the result should look like this:</p><p><img sf-image-responsive="true" src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-08/03_-signup_screen.png?sfvrsn=9d87fe8f_2" title="03_ signup_screen" alt="2. SignUp Page" /></p><h2 id="conclusion">Conclusion</h2><p>I hope this article helps you understand how to recreate a modern UI from scratch using .NET MAUI.  From building custom gradients with <strong>LinearGradientBrush</strong> and <strong>RadialGradientBrush</strong>, to structuring layouts with Grid, and creating a dynamic form using the <strong>Telerik DataForm,</strong> you now have a solid foundation to build clean and modern interfaces.</p><p>The best part is that these are concepts you can easily reuse and adapt to your own projects to create more polished and visually appealing apps. </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><hr /><blockquote><p>Remember, you can try Telerik UI for .NET MAUI free for 30 days.</p><br /><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/17411672.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:159397c1-5f5f-46d3-bd06-07c7be55ec21</id>
    <title type="text">4 Rating Card UI Ideas in .NET MAUI</title>
    <summary type="text">Enable users to provide feedback rating with these four variations of rating cards for your .NET MAUI app.</summary>
    <published>2026-08-03T15:33:09Z</published>
    <updated>2026-10-16T23:38:55Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17403337/4-rating-card-ui-ideas-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Enable users to provide feedback rating with these four variations of rating cards for your .NET MAUI app.</span></p><p>When we talk about feedback, we often think of the negative kind, like critiques or complaints. It makes sense, since they&rsquo;re the ones that stand out the most, even if just one out of 1,000 is negative. But that&rsquo;s not the full story.</p><p>There are also users who are enjoying your app, who are having a great experience &hellip; but simply don&rsquo;t say it. And many times, it&rsquo;s not because they don&rsquo;t want to, but because they don&rsquo;t have a way to do it. We&rsquo;re not giving them the space or the tools to express how they feel.</p><p>That&rsquo;s why it&rsquo;s key to add touchpoints in our apps where users can rate what they use from a specific module to the entire app through a rating and even a comment.</p><p>So, in this article, I&rsquo;m bringing you four rating UI ideas that we&rsquo;ll be building in .NET MAUI. </p><h2 id="-environment-setup"> Environment Setup</h2><p>You&rsquo;ll learn how to take advantage of some of the powerful Progress Telerik UI for .NET MAUI components in this post. If you don&rsquo;t have the .NET MAUI library installed yet, visit the <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/quickstart">quick start page</a>, which explains step-by-step how to install Telerik UI for .NET MAUI, download the license key, configure the Telerik package source and install the Telerik MCP server (if needed).</p><h2 id="let’s-start">Let&rsquo;s Start!</h2><p>Basically, we&rsquo;ll be building four different UI ideas, all focused on collecting user ratings. To achieve this, we&rsquo;ll use two key Telerik components: .NET MAUI Rating and .NET MAUI ProgressBar.</p><p>We&rsquo;ll create one .xaml page for each UI. After completing the Environment Setup in your project, remember that each .xaml page must include the required namespace for the Rating control and, when needed, the ProgressBar control. (Not all screens will use the ProgressBar.)</p><p>Your namespace should look like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">xmlns:telerik="clr-namespace:Telerik.Maui.Controls;assembly=Telerik.Maui.Controls"
</code></pre><h2 id="creating-the-example-structure">Creating the Example Structure</h2><p>Each of the four cards we&rsquo;ll build can be implemented in different ways, such as a <strong>Popup</strong> or a <strong>BottomSheet</strong>, depending on what best fits your app&rsquo;s needs.</p><p>For this example, we&rsquo;ll define a reusable Border with shadows that will act as the base container for each card.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Border 
BackgroundColor="White" 
StrokeThickness="0" 
StrokeShape="RoundRectangle 28" 
VerticalOptions="Center" 
HorizontalOptions="Center" 
WidthRequest="360" 
HeightRequest="520"&gt;
  
&lt;Border.Shadow&gt; 
    &lt;Shadow 
    Brush="#000000" 
    Opacity="0.15" 
    Radius="20" 
    Offset="0,10" /&gt; 
&lt;/Border.Shadow&gt;
 
    &lt;!-- Add the layout here --&gt;

&lt;/Border&gt;
</code></pre><h2 id="friendly-star-ui">1. Friendly Star UI</h2><p>This design is inspired by a <a target="_blank" href="https://dribbble.com/shots/23169802-Rating-Dialog-UI">Dribbble</a> concept and has a friendly, soft and playful style. This first UI is perfect for apps that want to ask for feedback in a warm and simple way, without making the rating experience feel too formal or intrusive.</p><p><img title="Friendly Star UI" src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/1-friendlystarui.png?sfvrsn=14a6d635_2" width="350" /></p><h3 id="starting-with-the-code">Starting with the Code</h3><p>Inside the previously defined Border, we&rsquo;ll create a grid with five rows, as shown below:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid RowDefinitions="140,Auto,Auto,Auto,Auto,*"&gt;
 
    &lt;!-- Add all UI elements here --&gt; 

&lt;/Grid&gt;
</code></pre><h3 id="header-with-rounded-image">Header with Rounded Image</h3><pre class=" language-xml"><code class="prism  language-xml">&lt;Image 
    Grid.Row="0" 
    Source="yellowbg.png" 
    Aspect="Fill" 
    HorizontalOptions="Fill" 
    VerticalOptions="Fill" 
    HeightRequest="160" /&gt;
 
&lt;Image 
    Grid.Row="0" 
    Source="star.png" 
    WidthRequest="140" 
    HeightRequest="140" 
    HorizontalOptions="Center" 
    VerticalOptions="End" 
    TranslationY="70" /&gt;
</code></pre><h3 id="rating-side">Rating Side</h3><p>Next, we&rsquo;ll add a simple text that says &ldquo;How Would You Rate Our App Experience?&rdquo; Additionally, we&rsquo;ll use the Telerik <strong>.NET MAUI Rating control</strong>.</p><p>I really love this control because it allows you to fully customize the colors of selected and unselected items. It&rsquo;s also not limited to stars, you can use different shapes or elements to represent the rating. I definitely encourage you to explore the .<a target="_blank" href="https://www.telerik.com/maui-ui/rating">NET MAUI Rating control</a>. You&rsquo;re going to love it!</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label 
    Grid.Row="1" 
    Text="How Would You Rate Our&amp;#10;App Experience?" 
    FontSize="20" 
    TextColor="#313A45" 
    HorizontalTextAlignment="Center" 
    Margin="30,80,30,0" /&gt;
 
&lt;telerik:RadShapeRating 
    Grid.Row="2" 
    Value="3" 
    ItemsCount="5" 
    SelectedItemStroke="#FFC44C" 
    SelectedItemFill="#FFC44C" 
    ItemFill="#D1D3DB" 
    ItemStroke ="#D1D3DB" 
    HeightRequest="28" 
    HorizontalOptions="Center" 
    Margin="0,32,0,0" /&gt;
</code></pre><p><strong>Submit button and footer text</strong></p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button 
    Grid.Row="3" 
    Text="Submit" 
    HeightRequest="35" 
    CornerRadius="29" 
    FontSize="15" 
    FontAttributes="Bold" 
    TextColor="White" 
    BackgroundColor="#0A8DF2" 
    Margin="38,54,38,0" /&gt;
 
&lt;Label 
    Grid.Row="4" 
    Text="No, Thanks!" 
    FontSize="15" 
    TextColor="#A7A7A7" 
    HorizontalOptions="Center" 
    Margin="0,24,0,0" /&gt;
</code></pre><h2 id="rating-summary-ui">2. Rating Summary UI</h2><p>Next, we&rsquo;ll continue with another <a target="_blank" href="https://dribbble.com/shots/12005607-Ratings-Card-UI-Design">Dribbble-inspired</a> UI. This one focuses on a <strong>rating summary</strong>, which is especially useful when you want to get a quick, overall view of what&rsquo;s happening with your app&rsquo;s feedback.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/2-ratingsummaryui.png?sfvrsn=c17c58a6_2" title="Rating Summary UI" width="350" /></p><p>In addition to the Telerik Rating control, we&rsquo;ll also incorporate the <a target="_blank" href="https://www.telerik.com/maui-ui/progressbar">Telerik ProgressBar</a>, which will help us visually represent the distribution of ratings across each level.</p><p>To show different ways of building layouts and working with components, we&rsquo;ll use a slightly different approach compared to the previous example. This time, we&rsquo;ll start with a <strong>VerticalStackLayout</strong> as our main container.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;VerticalStackLayout Spacing="18" VerticalOptions="Center" Margin="32"&gt; 
    &lt;! -- Add all the elements here -- &gt;  
&lt;/VerticalStackLayout&gt;
</code></pre><h3 id="customers-reviews-and-rounded-rating-bar">Customers Reviews and Rounded Rating Bar</h3><p>Along with the text, we&rsquo;ll use a HorizontalStackLayout to organize the elements, and we&rsquo;ll also add the RadShapeRating control.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label 
    Text="Customer reviews" 
    FontSize="20" 
    FontAttributes="Bold" 
    HorizontalTextAlignment="Center" /&gt;
 
&lt;Border 
    BackgroundColor="#F8F9FF" 
    StrokeThickness="0" 
    StrokeShape="RoundRectangle 24" 
    Padding="18,12" 
    HorizontalOptions="Center"&gt;
 
    &lt;HorizontalStackLayout Spacing="18"&gt; 
    &lt;telerik:RadShapeRating 
    Value="5" 
    ItemsCount="5" 
    HeightRequest="20" 
    SelectedItemStroke="#FFC44C" 
    SelectedItemFill="#FFC44C" 
    ItemFill="#D1D3DB" 
    ItemStroke ="#D1D3DB" /&gt;
     
    &lt;Label 
    Text="4.7 out of 5" 
    FontSize="13" 
    VerticalOptions="Center" /&gt; 
    &lt;/HorizontalStackLayout&gt; 
&lt;/Border&gt;

&lt;Label Text="40 customer ratings" 
    FontSize="13" 
    TextColor="#7A7A85" 
    HorizontalTextAlignment="Center" 
    Margin="0,-16,0,20" /&gt;
</code></pre><h3 id="adding-the-rating-breakdown-by-star">Adding the Rating Breakdown by Star</h3><p>Now, we&rsquo;ll add the remaining elements of the screen, including the <strong>ProgressBar</strong> component from Progress Telerik for each rating level.</p><p>To make it easier to understand, especially if you&rsquo;re just getting started in .NET MAUI, I&rsquo;ve kept this example very simple. However, you can make it much cleaner and more reusable by using styles or by generating these items from a list.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid ColumnDefinitions="70,*,50" ColumnSpacing="12"&gt; 
    &lt;Label Text="5 star" FontSize="13" TextColor="#3478D9" /&gt; 
    &lt;telerik:RadLinearProgressBar 
    Grid.Column="1" 
    Value="84" 
    HeightRequest="10" 
    ProgressFill="#FFC83D" 
    ProgressCornerRadius="15" 
    TrackCornerRadius="15" 
    TrackFill="#F5F7FF" /&gt; 
    &lt;Label Grid.Column="2" Text="84%" FontSize="13"/&gt; 
&lt;/Grid&gt;

&lt;Grid ColumnDefinitions="70,*,50" ColumnSpacing="12"&gt; 
&lt;Label Text="4 star" FontSize="13" TextColor="#3478D9" /&gt; 
    &lt;telerik:RadLinearProgressBar 
    Grid.Column="1" 
    Value="9" 
    HeightRequest="10" 
    ProgressCornerRadius="15" 
    TrackCornerRadius="15" 
    ProgressFill="#FFC83D" 
    TrackFill="#F5F7FF" /&gt; 
&lt;Label Grid.Column="2" Text="9%" FontSize="13" /&gt; 
&lt;/Grid&gt;

&lt;Grid ColumnDefinitions="70,*,50" ColumnSpacing="12"&gt; 
&lt;Label Text="3 star" FontSize="13" TextColor="#3478D9" /&gt; 
    &lt;telerik:RadLinearProgressBar 
    Grid.Column="1" 
    Value="4" 
    HeightRequest="10" 
    ProgressCornerRadius="15" 
    TrackCornerRadius="15" 
    ProgressFill="#FFC83D" 
    TrackFill="#F5F7FF" /&gt; 
    &lt;Label Grid.Column="2" Text="4%" FontSize="13" /&gt; 
&lt;/Grid&gt; 
&lt;Grid ColumnDefinitions="70,*,50" ColumnSpacing="12"&gt; 
&lt;Label Text="2 star" FontSize="13" TextColor="#3478D9" /&gt; 
    &lt;telerik:RadLinearProgressBar 
    Grid.Column="1" 
    Value="2" 
    HeightRequest="10" 
    ProgressFill="#FFC83D" 
    ProgressCornerRadius="15" 
    TrackCornerRadius="15" 
    TrackFill="#F5F7FF" /&gt; 
&lt;Label Grid.Column="2" Text="2%" FontSize="13" /&gt; 
&lt;/Grid&gt; 
&lt;Grid ColumnDefinitions="70,*,50" ColumnSpacing="12"&gt; 

&lt;Label Text="1 star" FontSize="13" TextColor="#3478D9" /&gt; 
&lt;telerik:RadLinearProgressBar 
    Grid.Column="1" 
    Value="1" 
    HeightRequest="10" 
    ProgressFill="#FFC83D" 
    ProgressCornerRadius="15" 
    TrackCornerRadius="15" 
    TrackFill="#F5F7FF" /&gt; 
    &lt;Label Grid.Column="2" Text="1%" FontSize="13" /&gt; 
&lt;/Grid&gt;  
&lt;Label 
    Text="How do we calculate ratings?" 
    FontSize="13" 
    TextColor="#3478D9" 
    HorizontalTextAlignment="Center" 
    Margin="0,18,0,0" /&gt;
</code></pre><h2 id="detailed-feedback-ui">3. Detailed Feedback UI</h2><p>Our third screen is a rating UI that also asks users to leave a comment about their score. It was inspired by a <a target="_blank" href="https://dribbble.com/shots/25493936-Ratings-Review-UI-Modal">Dribbble design</a>, and for this example, we modified it slightly.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/3-detailedfeedbackui.png?sfvrsn=7b728b3e_2" title="Detailed Feedback UI" width="350" /></p><p>For this card, our main layout will be a <strong>Grid</strong>:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid RowDefinitions="Auto,Auto,Auto,Auto,150,Auto" ColumnDefinitions="*,*" RowSpacing="20" ColumnSpacing="12" Padding="32"&gt; 
    &lt;! -- Add all the elements here -- &gt; 
&lt;/Grid&gt;
</code></pre><p>Adding the Label and <strong>Telerik Rating Control:</strong></p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label
    Grid.Row="0"
    Grid.Column="0"
    Grid.ColumnSpan="2"
    Text="Rate Our App!"
    FontSize="20"
    FontAttributes="Bold" /&gt;

&lt;Label 
    Grid.Row="1" 
    Grid.ColumnSpan="2" 
    Text="Help us improve our tool to best suit your needs by rating us here!" 
    FontSize="14"/&gt;
 
&lt;telerik:RadShapeRating 
    Grid.Row="2" 
    Grid.ColumnSpan="2" 
    Value="3" 
    ItemsCount="5" 
    HeightRequest="30" 
    ItemsSpacing="30" 
    SelectedItemStroke="#FFC44C" 
    SelectedItemFill="#FFC44C" 
    ItemStroke ="#2a2f39"
    HorizontalOptions="Center" /&gt;
    
&lt;Label 
    Grid.Row="3" 
    Grid.ColumnSpan="2" 
    Text="Can you tell us more?" 
    FontSize="12" 
    FontAttributes="Bold" /&gt;
 
&lt;Editor 
    Grid.Row="4" 
    Grid.ColumnSpan="2" 
    Placeholder="Fast and easy to use tool." 
    FontSize="15"
    BackgroundColor="White" /&gt;

&lt;Button 
    Grid.Row="5" 
    Grid.Column="0" 
    Text="Cancel" 
    FontAttributes="Bold" 
    HeightRequest="50" 
    CornerRadius="8" 
    BackgroundColor="White" 
    TextColor="#111827" 
    BorderColor="#E5E7EB" 
    BorderWidth="1" /&gt; 
    
&lt;Button 
    Grid.Row="5" 
    Grid.Column="1" 
    Text="Submit" 
    HeightRequest="50" 
    CornerRadius="8" 
    BackgroundColor="#651FFF" 
    TextColor="White" /&gt;
</code></pre><h2 id="multi-criteria-rating-ui">4. Multi-Criteria Rating UI</h2><p>We&rsquo;ve reached our final UI!!  And I&rsquo;m sure you&rsquo;ve learned a lot along the way!</p><p>This final design takes things a step further by allowing users to rate multiple criteria or categories, along with leaving a comment. Just like the previous examples, it was inspired by a <a target="_blank" href="https://dribbble.com/shots/25938656-Feedback-Ratings-Card-UI">Dribbble</a> design.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/4-multicriteriaratingui.png?sfvrsn=c3ad3f6b_2" title="Multi-Criteria Rating UI" width="350" /></p><p>For this card, our main layout will also be a <strong>Grid</strong>:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,80,Auto" 
    ColumnDefinitions="*,*" 
    RowSpacing="14" 
    Padding="15" 
    ColumnSpacing="14"&gt;
 
    &lt;! -- Add all the elements here -- &gt; 

&lt;/Grid&gt;
</code></pre><p>And let&rsquo;s add all the remaining elements:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label
    Grid.Row="0"
    Grid.Column="0"
    Grid.ColumnSpan="2"
    Text="Rate Our App!"
    FontSize="22"
    FontAttributes="Bold" /&gt;

&lt;Label
    Grid.Row="1"
    Grid.ColumnSpan="2"
    Text="How was the reliability and quality of work?"
    FontSize="15"
    Margin="0,6,0,10" /&gt;
    
&lt;Label
    Grid.Row="2"
    Grid.ColumnSpan="2"
    Text="Communication"
    FontSize="13"
    FontAttributes="Bold" /&gt;

&lt;telerik:RadShapeRating
    Grid.Row="3"
    Grid.ColumnSpan="2"
    Value="4"
    ItemsCount="5"
    HeightRequest="20"
    SelectedItemStroke="#FFC44C"
    SelectedItemFill="#FFC44C"
    HorizontalOptions="Start" /&gt;

&lt;Label
Grid.Row="4"
Grid.ColumnSpan="2"
Text="Punctuality"
FontSize="13"
FontAttributes="Bold" /&gt;

&lt;telerik:RadShapeRating
Grid.Row="5"
Grid.ColumnSpan="2" 
Value="3"
ItemsCount="5"
HeightRequest="20"
SelectedItemStroke="#FFC44C"
SelectedItemFill="#FFC44C"
HorizontalOptions="Start" /&gt;

&lt;Label
    Grid.Row="6"
    Grid.ColumnSpan="2"
    Text="Eye for Detail"
    FontSize="13"
    FontAttributes="Bold" /&gt;
    
&lt;telerik:RadShapeRating
    Grid.Row="7"
    Grid.ColumnSpan="2"
    Value="2"
    ItemsCount="5"
    HeightRequest="20"
    SelectedItemStroke="#FFC44C"
    SelectedItemFill="#FFC44C"
    HorizontalOptions="Start" /&gt;
    
&lt;Label
    Grid.Row="8"
    Grid.ColumnSpan="2"
    Text="Efficiency"
    FontSize="13"
    FontAttributes="Bold" /&gt;

&lt;telerik:RadShapeRating
    Grid.Row="9"
    Grid.ColumnSpan="2"
    Value="4"
    ItemsCount="5"
    HeightRequest="20"
    SelectedItemStroke="#FFC44C"
    SelectedItemFill="#FFC44C"
    HorizontalOptions="Start" /&gt;

&lt;Label
    Grid.Row="10"
    Grid.ColumnSpan="2"
    Text="Can you tell us more?"
    FontSize="14"
    FontAttributes="Bold" /&gt;

&lt;Editor 
Grid.Row="11"
Grid.ColumnSpan="2"
Placeholder="Add feedback"
FontSize="13"
PlaceholderColor="#9CA3AF"
BackgroundColor="White" /&gt;

&lt;Button
    Grid.Row="12"
    Grid.Column="0"
    Text="Cancel"
    HeightRequest="20"
    CornerRadius="8" 
    FontSize="16"
    FontAttributes="Bold"
    BackgroundColor="White"
    TextColor="#111827"
    BorderColor="#E5E7EB"
    BorderWidth="1" /&gt;

&lt;Button
    Grid.Row="12"
    Grid.Column="1"
    Text="Submit"
    HeightRequest="20"
    CornerRadius="8"
    FontSize="16"
    FontAttributes="Bold"
    BackgroundColor="#651FFF"
    TextColor="White" /&gt;
</code></pre><p>✍️ If you want to make it even more engaging, you can use a list to avoid repeating each category with its rating and even add some styling!</p><h2 id="conclusion">Conclusion</h2><p>All set!  We&rsquo;ve now built all four rating UI interfaces. Below, you can see how each one looks:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/5-alluiexamples.png?sfvrsn=4d64b92_2" title="Multi-Criteria Rating UI" /></p><p>I hope these four rating UI ideas inspire you to create more interactive and useful feedback experiences in your .NET MAUI apps! </p><p>Remember, ratings are not only about collecting numbers. They&rsquo;re also a great way to understand how users feel and what you can keep improving.</p><p>If you have any questions or would like me to explain any part in more detail, feel free to leave a comment, I&rsquo;ll be happy to help!  See you in the next article! &zwj;♀️</p><p>Remember, Telerik UI for .NET MAUI comes with a free 30-day trial, so you can experiment with these examples yourself!</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/17403337.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:0b4fd80d-abe7-433e-9d53-bda4cd0e9961</id>
    <title type="text">Top Common Handlers in .NET MAUI</title>
    <summary type="text">Connect your .NET MAUI cross-platform controls with corresponding platform-specific controls using handlers. Here are some example use cases where handlers are most useful.</summary>
    <published>2026-07-27T15:52:15Z</published>
    <updated>2026-10-16T23:38:55Z</updated>
    <author>
      <name>Héctor Pérez </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17388205/top-common-handlers-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Connect your .NET MAUI cross-platform controls with corresponding platform-specific controls using handlers. Here are some example use cases where handlers are most useful.</span></p><p>Handlers in .NET MAUI are the way to connect cross-platform controls with their native views on each platform. They offer a clean, decoupled and high-performance design. In this article we will analyze some scenarios where they are especially useful to solve certain problems. Let&rsquo;s go!</p><h2 id="understanding-handlers-in-.net-maui">Understanding Handlers in .NET MAUI</h2><p>A handler in .NET MAUI is a special class that maps a cross-platform control to its native control. When we create the user interface in XAML, we use these cross-platform controls to build interfaces inside content pages, which are translated to native controls. For example, a .NET MAUI <code>Entry</code> control is mapped to an Android <code>AppCompatEditText</code> control, an iOS / Mac Catalyst <code>UITextField</code> control and a <code>TextBox</code> control on Windows.</p><p>At this point, you may wonder about the usefulness of handlers in your projects. The answer is that you can use them to customize controls and solve a range of problems: changing the default appearance of controls that cannot be done from XAML controls, accessing the properties of each native control, allowing you to change behavior to perform validations, etc.</p><p>Handlers can be used to:</p><ul><li>Remove or modify elements of a control (like an underline, border, etc.)</li><li>Add functionality to a control (such as search capabilities)</li><li>Create custom controls</li></ul><p>Knowing about handlers is going a step further in your technical skills in .NET MAUI, so I highly recommend learning about them in depth.</p><h3 id="ways-to-customize-handlers-in-.net-maui">Ways to Customize Handlers in .NET MAUI</h3><p>In .NET MAUI, there are several ways to customize a handler, including:</p><ul><li><code>Mapper.AppendToMapping()</code>: To perform customizations after the default mapping</li><li><code>CommandMapper.AppendToMapping()</code>: To intercept actions</li><li><code>HandlerChanged</code>: For a specific instance</li></ul><p>In the above list you may have noticed the term <strong>Mapping</strong>, which refers to a dictionary of configurations that define how a control is rendered.</p><p>The way we connect to the handler will define which instances in the application we will affect through the handler. Let&rsquo;s do some practical exercises to better understand them, solving common but simple problems in customizing native controls.</p><p>For these demonstrations, I created a new project using the <strong>.NET MAUI App</strong> template without sample content. Next, I created a folder called <code>Handlers</code> and inside a static class called <code>HandlerCustomizations</code>:</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">HandlerCustomizations</span>
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">RegisterHandlers</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, you need to register the new class in <code>Program.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> <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>
        builder
            <span class="token punctuation">.</span><span class="token generic-method function">UseMauiApp<span class="token punctuation">&lt;</span>App<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 function">ConfigureMauiHandlers</span><span class="token punctuation">(</span>_ <span class="token operator">=</span><span class="token operator">&gt;</span>
            <span class="token punctuation">{</span>                
                HandlerCustomizations<span class="token punctuation">.</span><span class="token function">RegisterHandlers</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>With the above ready, we are now prepared to analyze common use cases for handlers.</p><h3 id="removing-underline-or-border-from-an-entry">Removing Underline or Border from an Entry</h3><p>Let&rsquo;s start with the most used handler across the .NET MAUI ecosystem. The problem is that .NET MAUI does not currently expose a property that allows removing the default lines on each native platform. For example, on Android a line appears under the text, on iOS a gray rectangle is shown and on Windows a border.</p><p>The handler code looks like the following:</p><pre class=" language-csharp"><code class="prism  language-csharp">        Microsoft<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Handlers<span class="token punctuation">.</span>EntryHandler<span class="token punctuation">.</span>Mapper<span class="token punctuation">.</span><span class="token function">AppendToMapping</span><span class="token punctuation">(</span><span class="token string">"BorderlessEntry"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>handler<span class="token punctuation">,</span> view<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span>
        <span class="token punctuation">{</span>
<span class="token preprocessor property">#<span class="token directive keyword">if</span> ANDROID</span>
            handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>BackgroundTintList <span class="token operator">=</span>
                Android<span class="token punctuation">.</span>Content<span class="token punctuation">.</span>Res<span class="token punctuation">.</span>ColorStateList<span class="token punctuation">.</span><span class="token function">ValueOf</span><span class="token punctuation">(</span>Android<span class="token punctuation">.</span>Graphics<span class="token punctuation">.</span>Color<span class="token punctuation">.</span>Transparent<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token preprocessor property">#<span class="token directive keyword">elif</span> IOS || MACCATALYST</span>
            handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>BorderStyle <span class="token operator">=</span> UIKit<span class="token punctuation">.</span>UITextBorderStyle<span class="token punctuation">.</span>None<span class="token punctuation">;</span>
<span class="token preprocessor property">#<span class="token directive keyword">elif</span> WINDOWS</span>
            handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>BorderThickness <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Microsoft<span class="token punctuation">.</span>UI<span class="token punctuation">.</span>Xaml<span class="token punctuation">.</span>Thickness</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token preprocessor property">#<span class="token directive keyword">endif</span></span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>In the code above, we access the control mapper <code>Entry</code>, which is the configuration dictionary, and add an extra customization called <code>BorderlessEntry</code>. You can also notice a callback that handles two parameters: <code>handler</code>, which is the access to the native control, and <code>view</code>, which is the <code>Entry</code> of .NET MAUI.</p><p>In each conditional compilation directive, a different behavior is specified according to the platform, using <code>handler.PlatformView</code>, and the native properties of each control. In the case of Android, we change the border color to transparent using <code>BackgroundTintList</code>. On iOS, the border is completely removed using the native property <code>BorderStyle</code>. And on Windows, <code>BorderThickness</code> is used to indicate a border thickness of zero.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-06/borderless-entry-control-ios-android.png?sfvrsn=fd6bc41a_2" alt="Borderless input control displayed on iOS and Android" /></p><p>In the image above you can see the Entry control used without an underline on Android, which allows combining with other controls to improve the visual appearance.</p><h3 id="modifying-properties-of-a-button">Modifying Properties of a Button</h3><p>Sometimes applications require a controlled visual style for buttons. For example, on Android the normal behavior is to add elevation and a ripple effect to all buttons. In .NET MAUI, there is no way to control these values natively directly on the control, so we can choose to use a handler again:</p><pre class=" language-csharp"><code class="prism  language-csharp">Microsoft<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Handlers<span class="token punctuation">.</span>ButtonHandler<span class="token punctuation">.</span>Mapper<span class="token punctuation">.</span><span class="token function">AppendToMapping</span><span class="token punctuation">(</span>
    <span class="token function">nameof</span><span class="token punctuation">(</span>Microsoft<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>IButton<span class="token punctuation">.</span>Background<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>handler<span class="token punctuation">,</span> view<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span>
<span class="token punctuation">{</span>
<span class="token preprocessor property">#<span class="token directive keyword">if</span> ANDROID</span>
    handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>StateListAnimator <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>Elevation <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>

    <span class="token keyword">var</span> rippleColor <span class="token operator">=</span> Android<span class="token punctuation">.</span>Graphics<span class="token punctuation">.</span>Color<span class="token punctuation">.</span><span class="token function">Argb</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">var</span> colorStateList <span class="token operator">=</span> Android<span class="token punctuation">.</span>Content<span class="token punctuation">.</span>Res<span class="token punctuation">.</span>ColorStateList<span class="token punctuation">.</span><span class="token function">ValueOf</span><span class="token punctuation">(</span>rippleColor<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>Background
                        <span class="token keyword">is</span> Android<span class="token punctuation">.</span>Graphics<span class="token punctuation">.</span>Drawables<span class="token punctuation">.</span>RippleDrawable rippleDrawable<span class="token punctuation">)</span>
        rippleDrawable<span class="token punctuation">.</span><span class="token function">SetColor</span><span class="token punctuation">(</span>colorStateList<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token preprocessor property">#<span class="token directive keyword">elif</span> IOS || MACCATALYST</span>
            handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>Alpha <span class="token operator">=</span> <span class="token number">1.0f</span><span class="token punctuation">;</span>
            handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>AdjustsImageWhenHighlighted <span class="token operator">=</span> <span class="token keyword">true</span><span class="token punctuation">;</span>
<span class="token preprocessor property">#<span class="token directive keyword">endif</span></span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>In the code above, these Android properties are modified:</p><ul><li><code>StateListAnimator</code>: Removes the elevation animation when pressed</li><li><code>rippleDrawable.SetColor</code>: Overrides the ripple effect color</li></ul><p>When running the application, we can see a customized ripple effect according to the defined ink color:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-06/native-button-ripple-handler.gif?sfvrsn=62fb21a7_2" alt="Native button with customized ripple effect" /></p><p>The previous handler demonstrates how to change default control effects using native properties.</p><h3 id="select-all-text-when-receiving-focus-in-an-entry">Select All Text When Receiving Focus in an Entry</h3><p>The following handler, which proves extremely useful, allows users to select all text in a <code>Entry</code> control when focusing, to then perform actions such as deleting the text, copying it, etc.</p><pre class=" language-csharp"><code class="prism  language-csharp">Microsoft<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Handlers<span class="token punctuation">.</span>EntryHandler<span class="token punctuation">.</span>Mapper<span class="token punctuation">.</span><span class="token function">AppendToMapping</span><span class="token punctuation">(</span>
    <span class="token string">"SelectAllOnFocus"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>handler<span class="token punctuation">,</span> view<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span>
    <span class="token punctuation">{</span>
<span class="token preprocessor property">#<span class="token directive keyword">if</span> ANDROID        </span>
        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>FocusChange <span class="token operator">+</span><span class="token operator">=</span> <span class="token punctuation">(</span>_<span class="token punctuation">,</span> e<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>HasFocus<span class="token punctuation">)</span>
                handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span><span class="token function">Post</span><span class="token punctuation">(</span>handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>SelectAll<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">elif</span> IOS || MACCATALYST        </span>
        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>EditingDidBegin <span class="token operator">+</span><span class="token operator">=</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>
            Microsoft<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>ApplicationModel<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> handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span><span class="token function">SelectAll</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 preprocessor property">#<span class="token directive keyword">endif</span></span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>The method <code>Post</code> on Android allows queuing the select-all action so the text selection is not overwritten. On the other hand on iOS the method <code>SelectAll</code> is invoked to carry out the selection, in the subscription to the <code>EditingDidBegin</code> event. This is because there is no <code>FocusChange</code> event similar to Android&rsquo;s.</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-06/autoselect-entry-on-focus.gif?sfvrsn=c0bf4d33_2" alt="Text inside input automatically selected when focused." /></p><h3 id="disabling-the-keyboard-of-an-entry-control">Disabling the Keyboard of an Entry Control</h3><p>The following useful .NET MAUI handler is the one that allows disabling the keyboard of an Entry control. Disabling keyboards is essential when creating applications where we will have a custom keyboard, such as a calculator app or a PIN input, and we want to show text input controls without the on-screen keyboard appearing.</p><p>To implement it, we will do it as follows:</p><pre class=" language-csharp"><code class="prism  language-csharp">Microsoft<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Handlers<span class="token punctuation">.</span>EntryHandler<span class="token punctuation">.</span>Mapper<span class="token punctuation">.</span><span class="token function">AppendToMapping</span><span class="token punctuation">(</span>
    <span class="token string">"DisableKeyboard"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>handler<span class="token punctuation">,</span> view<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>view<span class="token punctuation">.</span>AutomationId <span class="token operator">!=</span> <span class="token string">"no-keyboard"</span><span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span>

<span class="token preprocessor property">#<span class="token directive keyword">if</span> ANDROID        </span>
        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>ShowSoftInputOnFocus <span class="token operator">=</span> <span class="token keyword">false</span><span class="token punctuation">;</span>
<span class="token preprocessor property">#<span class="token directive keyword">elif</span> IOS || MACCATALYST        </span>
        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>InputView <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UIKit<span class="token punctuation">.</span>UIView</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">endif</span></span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>In the previous code, in the Android section the property <code>ShowSoftInputOnFocus</code> with a false value prevents the keyboard from appearing when focusing the field, while on the iOS side, <code>InputView</code> replaces the keyboard with an empty view, preventing the keyboard from appearing.</p><h3 id="datepickertimepicker-text-alignment">DatePicker/TimePicker: Text Alignment</h3><p>A common case that users want in mobile applications is to center the text in the <code>DatePicker</code> and <code>TimePicker</code> controls, which is not possible to do natively from XAML code in .NET MAUI.</p><p>To achieve this, we can once again resort to handlers. On this occasion, the code used will be the following:</p><pre class=" language-csharp"><code class="prism  language-csharp">Microsoft<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Handlers<span class="token punctuation">.</span>DatePickerHandler<span class="token punctuation">.</span>Mapper<span class="token punctuation">.</span><span class="token function">AppendToMapping</span><span class="token punctuation">(</span>
    <span class="token string">"CenterDateText"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>handler<span class="token punctuation">,</span> view<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span>
    <span class="token punctuation">{</span>
<span class="token preprocessor property">#<span class="token directive keyword">if</span> ANDROID</span>
        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>Gravity <span class="token operator">=</span> Android<span class="token punctuation">.</span>Views<span class="token punctuation">.</span>GravityFlags<span class="token punctuation">.</span>Center<span class="token punctuation">;</span>
<span class="token preprocessor property">#<span class="token directive keyword">elif</span> IOS || MACCATALYST                    </span>
        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>TextAlignment <span class="token operator">=</span> UIKit<span class="token punctuation">.</span>UITextAlignment<span class="token punctuation">.</span>Center<span class="token punctuation">;</span>
<span class="token preprocessor property">#<span class="token directive keyword">endif</span></span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

Microsoft<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Handlers<span class="token punctuation">.</span>TimePickerHandler<span class="token punctuation">.</span>Mapper<span class="token punctuation">.</span><span class="token function">AppendToMapping</span><span class="token punctuation">(</span>
    <span class="token string">"CenterTimeText"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>handler<span class="token punctuation">,</span> view<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span>
    <span class="token punctuation">{</span>
<span class="token preprocessor property">#<span class="token directive keyword">if</span> ANDROID</span>
        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>Gravity <span class="token operator">=</span> Android<span class="token punctuation">.</span>Views<span class="token punctuation">.</span>GravityFlags<span class="token punctuation">.</span>Center<span class="token punctuation">;</span>
<span class="token preprocessor property">#<span class="token directive keyword">elif</span> IOS || MACCATALYST</span>
        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>TextAlignment <span class="token operator">=</span> UIKit<span class="token punctuation">.</span>UITextAlignment<span class="token punctuation">.</span>Center<span class="token punctuation">;</span>
<span class="token preprocessor property">#<span class="token directive keyword">endif</span></span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>In the handler, the property <code>Gravity</code> is used on Android for both <code>DatePicker</code> and <code>TimePicker</code>, which allows aligning the text to the position we need. In the case of iOS, the <code>TextAlignment</code> property is used, which allows the same result:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-06/centered-text-datepicker-timepicker.png?sfvrsn=9b7a92de_2" alt="Centered text within DatePicker and TimePicker controls" /></p><p>Without a doubt, it is a small handler that can solve a common visual problem.</p><h3 id="entry-with-native-validation">Entry with Native Validation</h3><p>Let&rsquo;s move on to a more complex case related to the usefulness of handlers. Imagine a scenario where you need to apply some kind of validation to all controls in the application. To achieve this, you can combine the use of events like <code>TextChanged</code> on Android and <code>EditingChanged</code> on iOS:</p><pre class=" language-csharp"><code class="prism  language-csharp">Microsoft<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Handlers<span class="token punctuation">.</span>EntryHandler<span class="token punctuation">.</span>Mapper<span class="token punctuation">.</span><span class="token function">AppendToMapping</span><span class="token punctuation">(</span>
    <span class="token string">"NativeEmailValidation"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>handler<span class="token punctuation">,</span> view<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span>
    <span class="token punctuation">{</span>                    
<span class="token preprocessor property">#<span class="token directive keyword">if</span> ANDROID</span>
        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>TextChanged <span class="token operator">+</span><span class="token operator">=</span> <span class="token punctuation">(</span>_<span class="token punctuation">,</span> e<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">var</span> text <span class="token operator">=</span> e<span class="token punctuation">.</span>Text<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <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>
            <span class="token keyword">var</span> isValid <span class="token operator">=</span> System<span class="token punctuation">.</span>Text<span class="token punctuation">.</span>RegularExpressions<span class="token punctuation">.</span>Regex<span class="token punctuation">.</span><span class="token function">IsMatch</span><span class="token punctuation">(</span>
                text<span class="token punctuation">,</span> <span class="token string">@"^[^@\s]+@[^@\s]+\.[^@\s]+$"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>Error <span class="token operator">=</span>
                <span class="token punctuation">(</span>isValid <span class="token operator">||</span> text<span class="token punctuation">.</span>Length <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token keyword">null</span> <span class="token punctuation">:</span> <span class="token string">"Invalid Email"</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">elif</span> IOS || MACCATALYST</span>
                    handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>EditingChanged <span class="token operator">+</span><span class="token operator">=</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>
                        <span class="token keyword">var</span> text <span class="token operator">=</span> handler<span class="token punctuation">.</span>PlatformView<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>
                        <span class="token keyword">var</span> isValid <span class="token operator">=</span> System<span class="token punctuation">.</span>Text<span class="token punctuation">.</span>RegularExpressions<span class="token punctuation">.</span>Regex<span class="token punctuation">.</span><span class="token function">IsMatch</span><span class="token punctuation">(</span>
                            text<span class="token punctuation">,</span> <span class="token string">@"^[^@\s]+@[^@\s]+\.[^@\s]+$"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

                        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>Layer<span class="token punctuation">.</span>CornerRadius <span class="token operator">=</span> <span class="token number">4f</span><span class="token punctuation">;</span>
                        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>Layer<span class="token punctuation">.</span>BorderColor <span class="token operator">=</span> <span class="token punctuation">(</span>isValid <span class="token operator">||</span> text<span class="token punctuation">.</span>Length <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
                            <span class="token operator">?</span> UIKit<span class="token punctuation">.</span>UIColor<span class="token punctuation">.</span>Clear<span class="token punctuation">.</span>CGColor
                            <span class="token punctuation">:</span> UIKit<span class="token punctuation">.</span>UIColor<span class="token punctuation">.</span>SystemRed<span class="token punctuation">.</span>CGColor<span class="token punctuation">;</span>
                        handler<span class="token punctuation">.</span>PlatformView<span class="token punctuation">.</span>Layer<span class="token punctuation">.</span>BorderWidth <span class="token operator">=</span>
                            <span class="token punctuation">(</span>isValid <span class="token operator">||</span> text<span class="token punctuation">.</span>Length <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token number">0f</span> <span class="token punctuation">:</span> <span class="token number">1f</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">endif</span></span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>Within the lambda expression that handles the text change, a regular expression validation is performed. In this example, an email address is validated to be correctly written, but any other validation can be carried out.</p><p>Finally, in the Android case, the <code>Error</code> property is used to indicate there is an error, while on iOS the control is colored in a more customized way:</p><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-06/email-validation-handler.gif?sfvrsn=7d4c7c23_2" alt="Server handler validating an email address input" /></p><p>The above approach leads us to imagine scenarios with more complexity and related to events, such as saving to a database after editing a text, preventing prohibited words from a dictionary, etc.</p><h2 id="conclusion">Conclusion</h2><p>Throughout this article, you have been able to see the usefulness of handlers in real, everyday scenarios. They are a controlled way to modify native properties of controls without having to wrestle with native classes on each platform.</p><p>As a final point, in my experience, if you need a higher degree of customization and want something that has been tested across all platforms, I recommend that instead of creating handlers you use prebuilt controls that have the capabilities you need, such as those from the Progress Telerik UI for <a target="_blank" href="https://www.telerik.com/maui-ui">.NET MAUI suite of controls</a>, which include the functionalities mentioned in the article and many more, without the need to create custom handlers. See you in the next article!</p><img src="https://feeds.telerik.com/link/23059/17388205.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:1b45ff15-d8c7-41f1-8f78-ea820cb4b515</id>
    <title type="text">Building a Healthcare UI with .NET MAUI</title>
    <summary type="text">You’ve probably seen a healthcare interface when you were scheduling a recent doctor’s appointment. Let’s see how to build one in .NET MAUI!</summary>
    <published>2026-07-20T21:05:40Z</published>
    <updated>2026-10-16T23:38:55Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17383624/building-healthcare-ui-net-maui"/>
    <content type="text"><![CDATA[<p><p><span class="featured">You&rsquo;ve probably seen a healthcare interface when you were scheduling a recent doctor&rsquo;s appointment. Let&rsquo;s see how to build one in .NET MAUI!</span></p><p>One of the biggest challenges when creating app interfaces is when design elements step a bit outside the conventional. These kinds of designs push us to think differently and get more creative when translating them into code. </p><p>In this article, I&rsquo;m bringing you a healthcare UI inspired by <a target="_blank" href="https://dribbble.com/shots/26097286-Online-Doctor-Appointment-App">this Dribbble doctor appointment UI design</a>. I have to admit, it&rsquo;s one of my favorites!  It gives us the perfect opportunity to apply some cool tricks that make our design look impressive and truly out of the box.</p><p>We&rsquo;ll be using some Progress Telerik <a target="_blank" href="https://www.telerik.com/maui-ui">UI for .NET MAUI components</a>, along with a CollectionView, but this time, we&rsquo;ll simulate different columns to achieve the layout we want. Plus, we&rsquo;ll rely on three properties that will become our best friends in this UI: <code>Rotation</code>, <code>TranslationY</code> and <code>TranslationX</code>.</p><p>So grab your cup of coffee or hot chocolate ☕ and let&rsquo;s build this together! ✨</p><h2 id="how-will-the-explanation-work">How Will the Explanation Work?</h2><p>So you can understand where we&rsquo;re headed, 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 this design, we took inspiration from an original Dribbble UI but made some adaptations and adjustments to align it with the goals of this article.</p><h2 id="-environment-setup"> Environment Setup</h2><p>You&rsquo;ll learn how to take advantage of some of the powerful Telerik UI for .NET MAUI components in this post. If you don&rsquo;t have the .NET MAUI library installed yet, visit the <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/get-started/quickstart">quick start page</a>, which explains step-by-step how to install Telerik UI for .NET MAUI, download the license key, configure the Telerik package source and install the Telerik MCP server (if needed).</p><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://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/01_design_structure.png?sfvrsn=27fe3f27_2" title="Visual structure" alt="" /></p><p>Alright, now that we&rsquo;ve broken our UI into clear blocks, it&rsquo;s time to bring everything to life with some code!  Let&rsquo;s start building each section step by step.</p><h2 id="block-1-intro">Block 1. Intro</h2><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/02_intro_block.png?sfvrsn=cc68d631_2" title="1. Intro Block" width="300" alt="" /></p><p>This first block is one of my favorites, as it brings a unique touch to the UI. It plays with the way the information is presented and introduces a slightly different style for the Get Started button. Since this block represents a full page, we&rsquo;ll break this explanation down into the following steps:</p><h3 id="creating-the-main-page-with-a-background-image">Creating the Main Page with a Background Image</h3><p>Let&rsquo;s start by creating a page called <strong>DoctorIntroPage.xaml</strong>. This page will contain a Grid as the main layout. The grid will have only one row, which will allow us to play with the overlapping effect between the background image and the rest of the elements. Right there, you&rsquo;ll also see exactly where the background image is added.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid RowDefinitions="*"&gt; 
    &lt;!-- Main image --&gt;
    &lt;Image Grid.Row="0" Source="doctor.jpg" Aspect="AspectFill" Margin="0,40,0,0"/&gt;
    
    &lt;!-- Add the rest of the code for the first block -- &gt;
&lt;/Grid&gt;
</code></pre><h3 id="creating-the-cards-and-the-get-started-button">Creating the Cards and the Get Started Button</h3><p>To continue with these elements, we&rsquo;ll add another Grid. This one will contain three rows and two columns:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid Grid.Row="0" RowDefinitions="auto,*,auto,auto" ColumnDefinitions="*,*" Padding="20,40,20,30"&gt; 
    &lt;!-- Add the rotated cards here -- &gt; 
    &lt;!-- Add the Get Started button here -- &gt; 
&lt;/Grid&gt;
</code></pre><blockquote><p>⚠️ Add the previous code exactly in the comment above that says <code>&lt;!-- Add the rest of the code for the first block --&gt;</code>.</p></blockquote><h3 id="rotated-cards">Rotated Cards</h3><p>Now, to add the cards, we&rsquo;ll use one of my favorite Telerik controls: <strong>Telerik Border for .NET MAUI.</strong> Make sure you follow the steps indicated in the Environment Setup section at the beginning of the article. After that, you just need to 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>To achieve the card effect, I mainly relied on the <code>Rotation</code> property. One card uses a value of 50, while the other uses -12, creating the effect of opposite rotations between them. In addition, I used the <code>TranslationX</code> and <code>TranslationY</code> properties to position the cards and make the overlapping effect more noticeable. In code, it would look like this:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadBorder Grid.Row="1" Grid.Column="0" 
    BackgroundColor="#f4f5fe" 
    CornerRadius="20" 
    HeightRequest="190" 
    WidthRequest="190" 
    TranslationX="20" 
    Rotation="5"&gt; 
&lt;Grid RowDefinitions="auto,*,auto" ColumnDefinitions="*,auto" Padding="15"&gt; 
    &lt;telerik:RadButton Grid.Row="0" Grid.Column="1" ImageSource="cardiogram" BackgroundColor="Black" HeightRequest="60" WidthRequest="60" CornerRadius="30"/&gt; 
    &lt;Label Grid.Row="1" Grid.Column="0" Text="Strengthen" FontAttributes="Bold" FontSize="16"/&gt; 
    &lt;Label Grid.Row="2" Grid.Column="0" Text="Support your heart with care and healthy lifestyle." FontSize="11" /&gt; 
&lt;/Grid&gt; 
&lt;/telerik:RadBorder&gt; 
&lt;telerik:RadBorder Grid.Row="1" Grid.Column="1" 
    BackgroundColor="#3d7ff5" 
    CornerRadius="20" 
    HeightRequest="190" 
    WidthRequest="190" 
    TranslationY="90" 
    TranslationX="-10" 
    Opacity="0.8" 
    Rotation="-12"&gt; 
    &lt;Grid RowDefinitions="auto,*,auto" ColumnDefinitions="auto,*" Padding="15"&gt; 
    &lt;telerik:RadButton Grid.Row="0" Grid.Column="0" ImageSource="stethoscope" BackgroundColor="White" HeightRequest="60" WidthRequest="60" CornerRadius="30"/&gt; 
    &lt;Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" TextColor="White" Text="Safeguard" FontAttributes="Bold" HorizontalTextAlignment="End" FontSize="16" /&gt; 
    &lt;Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" TextColor="White" Text="Reduce risks with regular check-ups and early ditention." HorizontalTextAlignment="Start" FontSize="11" /&gt; 
    &lt;/Grid&gt; 
&lt;/telerik:RadBorder&gt;
</code></pre><h3 id="finally-let’s-add-the-get-started-button">Finally, Let&rsquo;s Add the Get Started Button</h3><p>To achieve this, we&rsquo;ll use a Telerik Border as a container to create a rounded black background behind the button. Inside it, we&rsquo;ll place a <a target="_blank" href="https://www.telerik.com/maui-ui/documentation/controls/button/overview">Telerik RadButton</a>.</p><p>Since we&rsquo;ve already added the namespace for RadBorder, you&rsquo;re all set, there&rsquo;s no need to add anything else to use RadButton.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadBorder Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" 
    BackgroundColor="Black" 
    Opacity="0.9" 
    CornerRadius="50" 
    HeightRequest="70" &gt; 
    &lt;Grid ColumnDefinitions="*,auto" Padding="15,5"&gt; 
    &lt;Label Grid.Column="0" Text="Get Started" FontSize="15" TextColor="White" VerticalTextAlignment="Center" /&gt; 
    &lt;telerik:RadButton Grid.Column="1" ImageSource="uprightarrow" BackgroundColor="#3d7ff5" HeightRequest="50" WidthRequest="50" CornerRadius="25" HorizontalOptions="End" Margin="10"/&gt; 
    &lt;/Grid&gt; 
&lt;/telerik:RadBorder&gt;
</code></pre><p>We&rsquo;ve finished this first block, and we already have our first page created!  Now, let&rsquo;s move on to the second block and keep building!</p><h2 id="block-2-header">Block 2. Header</h2><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/03_header_block.png?sfvrsn=e290109b_2" title="2. Header Block" width="300" alt="" /></p><p>We&rsquo;ve finished this first section, and our first page is already up and running!  Now, let&rsquo;s move on to the second section.</p><p>This time, we&rsquo;re going to create a page called <strong>DoctorDetailsPage.xaml</strong>. Set the background color of this page to #f4f5fe and let&rsquo;s define the main layout using a Grid. This Grid will have five rows and three columns, as shown below:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Grid RowDefinitions="auto,auto,auto,auto,auto,*" 
    ColumnDefinitions="*,auto,auto" 
    Padding="20,30,20,0"&gt; 
    &lt;!-- Add the header block here -- &gt; 
    &lt;!-- Add the appointment block here -- &gt; 
    &lt;!-- Add the available doctors block here -- &gt; 
&lt;/Grid&gt;
</code></pre><p>Now, within the Grid, let&rsquo;s add the name and email:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Grid.Row="0" Grid.Column="0" Text="Ronalds S." FontSize="24" FontAttributes="Bold" /&gt;

&lt;Label Grid.Row="1" Grid.Column="0" Text="ronalds@gmail.com" FontSize="14"/&gt;
</code></pre><p>Next, we&rsquo;ll add a <strong>Telerik RadBorder</strong> control (remember to include the corresponding namespace, just like we did on the previous page). Inside it, we&rsquo;ll place an image along with a rounded button:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadBorder Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" Grid.ColumnSpan="2" 
    Margin="0,0,0,40" 
    BackgroundColor="White" 
    CornerRadius="120" 
    VerticalOptions="Start"&gt; 
    &lt;HorizontalStackLayout&gt; 
    &lt;telerik:RadButton ImageSource="plus" BackgroundColor="#ebecfb" HeightRequest="60" WidthRequest="60" CornerRadius="30" Margin="5,2,0,1"/&gt; 
    &lt;Image Source="doctoravatar" HeightRequest="60" WidthRequest="60" Aspect="AspectFill" Margin="5,2"/&gt; 
    &lt;/HorizontalStackLayout&gt; 
&lt;/telerik:RadBorder&gt;
</code></pre><h2 id="block-3-appointment">Block 3. Appointment</h2><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/04_appointment_block.png?sfvrsn=596533c1_2" title="3. Appointment Block" width="300" alt="" /></p><p>The Appointment block contains different elements, which are achieved by adding a few Label controls along with a Telerik RadBorder, as shown below:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Grid.Row="2" Grid.Column="0" Text="Today" FontSize="14" /&gt; 
&lt;Label Grid.Row="3" Grid.Column="0" Text="Appointment" FontAttributes="Bold" FontSize="16" /&gt; 
&lt;Label Grid.Row="2" Grid.Column="2" Text="See all" HorizontalTextAlignment="End" TextColor="#3d7ff5" FontSize="14" /&gt;
 
&lt;telerik:RadBorder Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="3" 
    BackgroundColor="#3d7ff5" 
    CornerRadius="120" 
    Margin="0,10,0,0" 
    HeightRequest="80" AutomationProperties.IsInAccessibleTree="True"&gt; 
    &lt;Grid ColumnDefinitions="auto,*" RowDefinitions="auto,auto,auto" VerticalOptions="Center"&gt; 
    &lt;Image Grid.Column="0" Grid.Row="0" Grid.RowSpan="3" Source="doctorjose" HeightRequest="80" WidthRequest="80" Aspect="AspectFill" Margin="5,2"/&gt; 
    &lt;Label Grid.Column="1" Grid.Row="0" Text="March 21, 10:00 AM" FontSize="10" TextColor="White" VerticalTextAlignment="End" /&gt; 
    &lt;Label Grid.Column="1" Grid.Row="1" Text="Dr. Suzanne Holroyd" FontSize="16" FontAttributes="Bold" TextColor="White"/&gt; 
    &lt;Label Grid.Column="1" Grid.Row="2" Text="Pulmonology" FontSize="10" TextColor="White" VerticalTextAlignment="Start" /&gt; 
    &lt;/Grid&gt;
&lt;/telerik:RadBorder&gt;
</code></pre><h2 id="block-4-available-doctors">Block 4. Available Doctors</h2><p><img src="https://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/05_available_doctors_block.png?sfvrsn=8c87ac81_2" title="4. Available Doctors Block" width="300" alt="" /></p><p>For our final block, we&rsquo;ll also use a Telerik RadBorder to simulate a white background with rounded top corners. Inside it, we&rsquo;ll add a Grid with two rows and three columns. Within this layout, we&rsquo;ll include the title label, two rounded buttons and, finally, a CollectionView.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;telerik:RadBorder Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="3" 
VerticalOptions="Fill" 
BackgroundColor="White" 
CornerRadius="30,30,0,0" 
Margin="-20,20,-20,0"&gt;

&lt;Grid RowDefinitions="auto,*" ColumnDefinitions="*,auto,auto" Padding="20,30,0,0"&gt; 
    &lt;Label Grid.Row="0" Grid.Column="0" Text="Select &amp;#10;Visit Type" FontSize="15" VerticalTextAlignment="End" FontAttributes="Bold"/&gt; 
    &lt;telerik:RadButton Grid.Row="0" Grid.Column="1" ImageSource="search" BackgroundColor="#ebecfb" HeightRequest="50" WidthRequest="50" CornerRadius="25" Margin="0,0,5,0" /&gt; 
    &lt;telerik:RadButton Grid.Row="0" Grid.Column="2" ImageSource="filter" BackgroundColor="#ebecfb" HeightRequest="50" WidthRequest="50" CornerRadius="25" /&gt;
    &lt;CollectionView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" 
    ItemsSource="{Binding specialists}"&gt; 
    &lt;CollectionView.ItemsLayout&gt; 
    &lt;GridItemsLayout Orientation="Horizontal" HorizontalItemSpacing="15" Span="2"/&gt; 
    &lt;/CollectionView.ItemsLayout&gt; 
    &lt;CollectionView.ItemTemplate&gt; 
    &lt;DataTemplate&gt; 
    &lt;telerik:RadBorder BackgroundColor="{Binding bgColor}" 
    CornerRadius="20" 
    HeightRequest="150" 
    WidthRequest="150"&gt; 
    &lt;Grid RowDefinitions="auto,auto,*,*" ColumnDefinitions="*,auto" Padding="15"&gt; 
    &lt;telerik:RadButton Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" ImageSource="rightupblack" BackgroundColor="{Binding btnColor}" HeightRequest="50" WidthRequest="50" CornerRadius="25"/&gt; 
    &lt;Label Grid.Row="0" Grid.Column="0" Text="{Binding Price}" FontAttributes="Bold" FontSize="16" TextColor="{Binding txColor}"/&gt; 
    &lt;Label Grid.Row="1" Grid.Column="0" Text="Per visit" FontAttributes="Bold" FontSize="10" TextColor="{Binding txColor}"/&gt; 
    &lt;Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Text="{Binding category}" TextColor="{Binding txColor}" FontAttributes="Bold" FontSize="12" VerticalTextAlignment="End"/&gt; 
    &lt;Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Text="{Binding description}" TextColor="{Binding txColor}" FontAttributes="Bold" FontSize="10"/&gt; 
    &lt;/Grid&gt; 
    &lt;/telerik:RadBorder&gt; 
    &lt;/DataTemplate&gt; 
    &lt;/CollectionView.ItemTemplate&gt; 
    &lt;/CollectionView&gt; 
&lt;/Grid&gt; 
&lt;/telerik:RadBorder&gt;
</code></pre><p>✍️ Yes! You might notice something different in the <strong>CollectionView</strong>.  Instead of a traditional list, the items are displayed in multiple columns. This is achieved by using a <strong>GridItemsLayout</strong> and setting the <code>Span</code> property, which allows us to organize the results into columns.</p><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://www.telerik.com/sfimages/default-source/blogs/2026/2026-07/06_complete_design_demo.png?sfvrsn=14317b2f_2" title="Complete design results" alt="" /></p><hr /><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, we explored how to build a doctor&rsquo;s office app UI using .NET MAUI with XAML. We walked through how to structure the UI into blocks, create designs using grids, apply overlapping effects and enhance the experience using Telerik components like RadBorder and RadButton.</p><p>I hope this article helps you take these ideas and apply them to your own projects! </p><p>If you have any questions or would like me to dive deeper into a specific part, feel free to leave a comment&mdash;I&rsquo;ll be happy to help! &nbsp;See you in the next article! &zwj;♀️</p><p>Remember, Telerik UI for .NET MAUI comes with a free 30-day trial. So you can play around in the meantime! </p><p><a href="https://www.telerik.com/try/ui-for-maui" target="_blank" class="Btn">Try Now</a></p></p><img src="https://feeds.telerik.com/link/23059/17383624.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:7d534c7b-328a-47e2-b23c-45a268c89b19</id>
    <title type="text">Goodbye ValueConverters, Hello C# Expressions in .NET MAUI</title>
    <summary type="text">C# Expressions mean you can now skip the Converters and add logic directly in your XAML using C#. This is great news for .MET MAUI developers!</summary>
    <published>2026-07-13T15:27:52Z</published>
    <updated>2026-10-16T23:38:55Z</updated>
    <author>
      <name>Leomaris Reyes </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23059/17379570/goodbye-valueconverters-hello-csharp-expressions-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">C# Expressions mean you can now skip the Converters and add logic directly in your XAML using C#. This is great news for .MET MAUI developers!</span></p><p>Improving and optimizing your code should be your top priority every single day. As a .NET MAUI developer, I know Converters are very familiar to you. They&rsquo;ve helped us transform data and adapt it to the UI. However, we can all agree that sometimes they made our code a bit more verbose than necessary.</p><p>But here&rsquo;s some <strong>BIG news </strong> &hellip; and honestly, one of the most impactful changes in recent times. The Microsoft team, always thinking about developer experience, now allows us to say goodbye to Converters and start using C# Expressions instead! </p><p>What does this mean? You can now add logic directly in your XAML using C#: perform math operations, use string interpolation, boolean logic and much more. In this article, we&rsquo;ll walk through before-and-after scenarios so you can clearly see how much code you can save, not to mention how much more readable and team-friendly your code will become.</p><p>Grab your coffee ☕ and let&rsquo;s get started!</p><h2 id="lets-start">Let&rsquo;s Start!</h2><p>Today, we&rsquo;ll dive directly into the code to explore the differences and how we can use them moving forward. Each example will be broken down into subtopics so you can clearly understand the before and after. </p><h2 id="case-1-simple-property-binding">Case 1: Simple Property Binding</h2><p>When we need to connect the value of a property with the UI, we typically use Bindings followed by the property name. For example, if we want to display values from properties like <code>FullName</code> or <code>Company</code>, we would write something like this:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="{Binding FullName}" /&gt;

&lt;Label Text="{Binding Company}" /&gt;
</code></pre><h3 id="applying-c-expressions">Applying C# Expressions</h3><p>Now, what if I told you that you can achieve the same result <strong>without using Bindings</strong>? </p><p>With C# Expressions, you can do it in two different ways:</p><p><strong> Implicit syntax</strong></p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="{FullName}" /&gt;

&lt;Label Text="{Company}" /&gt;
</code></pre><p><strong> Explicit syntax</strong></p><p>You can also use the <code>= prefix</code> to make it more explicit that you&rsquo;re using a C# expression.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="{= FullName}" /&gt;

&lt;Label Text="{= Company}" /&gt;
</code></pre><p>There is no functional difference between the implicit and explicit approaches; both achieve the same result. You can use whichever style you feel more comfortable with or that best fits your team&rsquo;s coding standards.</p><h2 id="case-2-string-interpolation">Case 2: String Interpolation</h2><p>We&rsquo;re used to formatting strings using <code>StringFormat</code>. For example, if we want to display a price like &ldquo;Total: $28 USD,&rdquo; we first need to define the Binding with the property, and then apply the format using <code>StringFormat='Total: ${0} USD'</code>.</p><p>If we need to include more properties in the format, we must keep adding placeholders, which can make the expression more complex and harder to read as it grows.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="{Binding Price, StringFormat='Total: ${0} USD'}" FontSize="18" TextColor="Green" /&gt;
</code></pre><h3 id="applying-c-expressions-1">Applying C# Expressions</h3><p>With C# Expressions, you can do it directly.  Notice how much simpler and more readable the same expression becomes compared to the previous approach:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="{=$'Total: ${Price} USD'}" FontSize="18" TextColor="Green" /&gt;
</code></pre><h2 id="case-3-multi-root-expressions-calculations">Case 3: Multi-root Expressions (Calculations)</h2><p>I&rsquo;m speechless  &hellip; you can now perform calculations directly in XAML.</p><p>Before seeing how this works now, let&rsquo;s look at how we&rsquo;ve traditionally handled this scenario. To achieve this before, we usually needed to create a computed property in the ViewModel, something like:</p><pre class=" language-csharp"><code class="prism  language-csharp">public decimal Subtotal =&gt; UnitPrice * ItemsCount;
</code></pre><p>And then bind it in XAML:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="{Binding Subtotal, StringFormat='Subtotal: ${0:F2}'}" 
    FontSize="20" 
    FontAttributes="Bold" /&gt;
</code></pre><h3 id="now-with-c-expressions">Now with C# Expressions</h3><p>One of the most exciting improvements is that we can now perform calculations directly in XAML.</p><p>For example, if we want to display the subtotal of a purchase based on the unit price and the number of items, we no longer need a computed property or a converter for that. We can write the expression exactly where we need it:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="{=$'Subtotal: ${UnitPrice * ItemsCount:F2}'}" 
    FontSize="20" 
    FontAttributes="Bold" /&gt;
</code></pre><h2 id="case-4-boolean-negations">Case 4: Boolean Negations</h2><p>In case you still had any doubts about saying goodbye to Converters &hellip; </p><p>Before, inverting a boolean value was not that straightforward. If you wanted to show or hide an element based on the opposite value of a property, you couldn&rsquo;t do it directly in XAML. This required creating a converter, registering it in the resources, and then applying it in the binding. A process that, for such a small piece of logic, ended up being unnecessarily complex.</p><p>For example, let&rsquo;s look at this scenario where we want to display a message when the user is not logged in:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="Please log in to continue" 
    IsVisible="{Binding IsLoggedIn, Converter={StaticResource BooleanInvertConverter}}" 
    TextColor="Red" 
    FontSize="16" /&gt;
</code></pre><p>And also:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;local:BooleanInvertConverter x:Key="BooleanInvertConverter" /&gt;

public class BooleanInvertConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)C
=&gt; !(bool)value;

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
=&gt; !(bool)value; 
}
</code></pre><h3 id="now-with-c-expressions-1">Now with C# Expressions</h3><p>Look how simple this becomes with just this small piece of code:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Label Text="Please log in to continue" 
    IsVisible="{=!IsLoggedIn}" 
    TextColor="Red" 
    FontSize="16" /&gt;
</code></pre><p>Just one line. No converters, no extra classes, no additional setup. </p><p>And of course, you can also work with boolean expressions without negation, like this:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Switch IsToggled="{HasAccount}" /&gt;
</code></pre><h2 id="case-5-lambda-event-handlers">Case 5: Lambda Event Handlers</h2><p>Traditionally, to handle events in .NET MAUI, we needed to create methods in the code-behind or define Commands in the ViewModel. This meant more code, more structure and, in many cases, more complexity than necessary.</p><p>But before we see how this looks now, let&rsquo;s take a look at how we&rsquo;ve been doing it so far:</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button Text="{Binding ClickCount, StringFormat='Clicked {0} times'}" 
    Command="{Binding IncrementCommand}" 
    BackgroundColor="DarkOrange" 
    TextColor="White" /&gt;
</code></pre><p>In the view model:</p><pre class=" language-csharp"><code class="prism  language-csharp">public ICommand IncrementCommand { get; } 
public int ClickCount { get; set; }
 
public MainViewModel()
{ 
IncrementCommand = new Command(() =&gt;
{ 
    ClickCount++; 
}); 
}
</code></pre><h3 id="now-with-c-expressions-2">Now with C# Expressions</h3><p>Thanks to C# Expressions, we can also use lambda expressions directly in XAML to handle events.  This allows us to execute logic inline, exactly where we need it, making the code more direct, cleaner and much easier to read for simple interactions.</p><pre class=" language-xml"><code class="prism  language-xml">&lt;Button Text="{=$'Clicked {ClickCount} times'}" 
    Clicked="{(s, e) =&gt; ClickCount++}" 
    BackgroundColor="DarkOrange" 
    TextColor="White" /&gt;
</code></pre><h2 id="conclusion">Conclusion</h2><p>And that&rsquo;s it!  In this article, we explored how C# Expressions are changing the way we build .NET MAUI apps. From simple bindings, string formatting and calculations, to boolean logic and even event handling&hellip; we saw how we can now write less code, make it more direct, and achieve things that previously required much more setup and effort.</p><p>I hope this article helps you start simplifying your own code and encourages you to take advantage of this more modern and expressive approach in your .NET MAUI applications.</p><p>If you have any questions or would like me to dive deeper into any of these scenarios, feel free to leave a comment, I&rsquo;ll be happy to help you! </p><p>See you in the next article! &zwj;♀️</p><h2 id="reference">Reference</h2><p>I used a video by Gerald Versluis as a reference for creating this article:</p><div data-sf-ec-immutable="" class="-sf-relative" contenteditable="false" style="width:560px;height:315px;"><div data-sf-disable-link-event=""><iframe width="560" height="315" src="https://www.youtube.com/embed/xPI8hLpyc5k?si=WhgcqoTyB5pV51fa" title="Gerald Versluis | RIP Converters, XAML C# Expressions are here" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"></iframe></div></div><img src="https://feeds.telerik.com/link/23059/17379570.gif" height="1" width="1"/>]]></content>
  </entry>
  <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-10-16T23:38:55Z</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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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-10-16T23:38:55Z</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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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-10-16T23:38:55Z</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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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-10-16T23:38:55Z</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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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://www.telerik.com/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-10-16T23:38:55Z</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://www.telerik.com/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://www.telerik.com/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>
</feed>
