﻿<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://community.devexpress.com/feed-stylesheets/rss.xsl" media="screen"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dx="https://www.devexpress.com/" xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>.NET MAUI Team Blog</title>
    <link>https://community.devexpress.com/Blogs/mobile/default.aspx</link>
    <description>.NET MAUI &amp; Xamarin Forms feature-rich mobile UI Controls for Android and iOS development: Data Grid, Scheduler, Chart, Tab View, Editors, and utility controls.</description>
    <language>en-US</language>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388210</guid>
      <link>https://community.devexpress.com/Blogs/mobile/archive/2024/11/04/net-maui-memory-profiling-identify-and-fix-memory-leaks.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.net+maui">.net maui</category>
      <category domain="https://community.devexpress.com/Tags/Android">Android</category>
      <category domain="https://community.devexpress.com/Tags/iOS">iOS</category>
      <category domain="https://community.devexpress.com/Tags/maui">maui</category>
      <category domain="https://community.devexpress.com/Tags/mobile">mobile</category>
      <category domain="https://community.devexpress.com/Tags/performance">performance</category>
      <title>.NET MAUI Memory Profiling — Identify and Fix Memory Leaks</title>
      <description>&lt;p&gt;&lt;span&gt;Why is proper memory management crucial when modern devices ship with gigabytes of RAM?&amp;nbsp;In simple terms, memory leaks can significantly degrade performance, drain device batteries, and/or crash an app.&amp;nbsp;&lt;/span&gt;In this blog post,&amp;nbsp;I&amp;#39;ll&amp;nbsp;outline common&amp;nbsp;.NET MAUI-related memory leaks and show you how to locate/address&amp;nbsp;leaks using&amp;nbsp;&lt;a href="https://marketplace.visualstudio.com/items?itemName=nromanov.dotnet-meteor" target="_blank"&gt;.NET Meteor&lt;/a&gt; and &lt;a href="https://github.com/1hub/dotnet-heapview" target="_blank"&gt;Heapview&lt;/a&gt;. If you&amp;#39;ve never used .NET Metear or Heapview, feel free to watch the following short YouTube video first:&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/faU1jIKIulc?si=t-pWBuEM5Lhbw4Yy" allowfullscreen="" style="width:560px;" referrerpolicy="strict-origin-when-cross-origin"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;h2&gt;&lt;span&gt;Common Memory Leaks in .NET MAUI&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;Before diving into common .NET MAUI memory leaks, let&amp;#39;s first review the fundamentals of .NET memory management. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;As you know, managed memory is overseen by the garbage collector (GC), which handles both memory allocation and deallocation when objects are no longer in use.&amp;nbsp;&lt;/span&gt;&lt;span&gt;Memory allocated to an object can only be reclaimed if no strong references to the object exist from other objects. The GC can detect cyclic references, so even if &lt;code&gt;ObjectA&lt;/code&gt;&amp;nbsp;and &lt;code&gt;ObjectB&lt;/code&gt; reference one another, they can still be collected and released.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;It&amp;#39;s important to remember that the garbage collector only manages .NET objects. If an object allocates unmanaged memory, you must call &lt;code&gt;Dispose&lt;/code&gt;&amp;nbsp;. You can do so explicitly or by adding the &lt;code&gt;using&lt;/code&gt; statement to the variable definition:&lt;/p&gt;&lt;/div&gt;&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp"&gt;//implicit dispose 
using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read) 

//explicit dispose
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read) 
//... 
fileStream.Dispose() &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;using&lt;/code&gt; statement ensures that the compiler automatically  calls&amp;nbsp;&lt;code&gt;Dispose&lt;/code&gt; when a variable goes out of scope.&lt;/p&gt;&lt;p&gt;With that brief overview, let&amp;#39;s review some common memory leaks in .NET MAUI-powered applications and what you can do to address them. If you&amp;#39;d like to follow along to this blog post, please download the following sample GitHub project:&amp;nbsp;&lt;/p&gt;&lt;a href="https://github.com/DevExpress-Examples/common-maui-memory-leaks" class="Button Gray"&gt;Download Test Application&lt;/a&gt;&lt;h3&gt;Reference from a long-lived object or static property&lt;/h3&gt;&lt;p&gt;One common cause of memory leaks is creating a strong reference from an object that persists for the entire application runtime. For example, if you reference a child page from &lt;code&gt;AppShell&lt;/code&gt;, the child page will never be released. The same issue can arise if you create a reference from a static property:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp" data-line="2, 11"&gt;public partial class AppShell : Shell { 
    public List&amp;lt;ContentPage&amp;gt; OpenedChildPages = new List&amp;lt;ContentPage&amp;gt;(); 
    public AppShell() { 
        InitializeComponent(); 
    } 
} 

public partial class DirectReferenceLeakPage : ContentPage { 
    public DirectReferenceLeakPage () { 
        InitializeComponent(); 
       ((AppShell)App.Current.MainPage).OpenedChildPages.Add(this);    
    } 
 } &lt;/code&gt;&lt;/pre&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20242108-MAUI-Memory-Profiling/Long-lived%20object%20reference%20leak.jpg" alt="Long-living reference memory leak"&gt;&lt;p&gt;To address&amp;nbsp;the leak, remove the strong reference in the &lt;code&gt;OnDisappearing&lt;/code&gt; event handler. If the same page instance can be opened multiple times, create the reference in the &lt;code&gt;OnAppearing&lt;/code&gt; event handler instead of the page constructor:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp"&gt;private void OnDisappearing(object sender, EventArgs e) { 
    ((AppShell)App.Current.MainPage).OpenedChildPages.Remove(this); 
} 

private void OnAppearing(object sender, EventArgs e) { 
    ((AppShell)App.Current.MainPage).OpenedChildPages.Add(this); 
} &lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;&lt;span style="color:#0f4761;"&gt;&lt;span&gt;Event &lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;andler &lt;/span&gt;&lt;span&gt;or &lt;/span&gt;&lt;span&gt;Function Delegate&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;When you subscribe to an event, the event source holds a reference to the subscriber (to be able to call its handler). A memory leak only occurs if you subscribe to a long-lived object event. If the event source and the subscriber have the same lifetime, leaks will not occur. For instance, subscribing to the &lt;code&gt;Clicked&lt;/code&gt; event of a &lt;code&gt;Button&lt;/code&gt; on the same page won&amp;#39;t cause a leak (because the .NET garbage collector detects cycles and releases objects that reference each other).&lt;/p&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20242108-MAUI-Memory-Profiling/Event%20handler%20leak_.jpg" alt="Event memory leak in .NET MAUI"&gt;&lt;p&gt;The following code will cause a leak because the long-lived&amp;nbsp;&lt;code&gt;Accelerometer&lt;/code&gt; object holds a reference to the &lt;code&gt;Accelerometer_ReadingChanged&lt;/code&gt; delegate:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp" data-line="5"&gt;public partial class EventLeakPage : ContentPage 
{ 
    public EventLeakPage() { 
        InitializeComponent(); 
        Accelerometer.ReadingChanged += Accelerometer_ReadingChanged; 
    } 
    private void Accelerometer_ReadingChanged(object sender, AccelerometerChangedEventArgs e) { 
        //... 
    } 
} &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The same issue can occur if you pass a function delegate to a long-lived object. A common example is the &lt;code&gt;Dispatcher.StartTimer&lt;/code&gt; method, which accepts a function delegate as its second parameter:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp" data-line="4"&gt;public partial class DelegateLeakPage : ContentPage { 
    public DelegateLeakPage() { 
        InitializeComponent(); 
        Dispatcher.StartTimer(TimeSpan.FromSeconds(1), TimerTick);    
    } 
    bool TimerTick() { 
         //...
    } 
} &lt;/code&gt;&lt;/pre&gt;&lt;div&gt;To address the issue, subscribe or unsubscribe from events when a page is displayed and hidden:&lt;/div&gt;&lt;pre&gt;&lt;code class="language-csharp"&gt;private void OnAppearing(object sender, EventArgs e) { 
   Accelerometer.ReadingChanged += Accelerometer_ReadingChanged; 
} 

private void OnDisappearing(object sender, EventArgs e) { 
   Accelerometer.ReadingChanged -= Accelerometer_ReadingChanged; 
} &lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Controls with a&amp;nbsp;Memory Leak&lt;/h3&gt;&lt;p&gt;If a page includes at least one control that isn&amp;#39;t properly released, it will prevent the entire page from being released. This happens because all .NET MAUI controls include a&amp;nbsp;&lt;code&gt;Parent&lt;/code&gt; property. All&amp;nbsp;references stored in &lt;code&gt;Parent&lt;/code&gt; point back to the page.&lt;/p&gt;
    &lt;img src="https://community.devexpress.com:443/blogs/mobile/20242108-MAUI-Memory-Profiling/Problematic%20control%20leak.jpg" alt="A control causing a memory leak" style="max-height:400px;"&gt;
&lt;p&gt;A potential fix is to&amp;nbsp;&lt;span&gt;replace the problematic component&amp;nbsp;with a different control or&lt;/span&gt; remove it when a user navigates to another page.&lt;/p&gt;&lt;h3&gt;Singleton View&lt;/h3&gt;&lt;div&gt;As you may know, &lt;em&gt;Dependency Injection (DI)&lt;/em&gt;&amp;nbsp;allows&amp;nbsp;you to register objects as transients or singletons. Transient objects are created anew each time they are requested from the DI container, whereas singleton objects are instantiated only once (with the DI container returning the same instance for each request).&lt;/div&gt;&lt;pre&gt;&lt;code class="language-csharp"&gt;mauiAppBuilder.Services.AddTransient&amp;lt;MyPage&amp;gt;(); 
mauiAppBuilder.Services.AddSingleton&amp;lt;MyPage&amp;gt;(); &lt;/code&gt;&lt;/pre&gt;&lt;div&gt;If you register a page as a singleton, the DI container will create only one instance of the page and reuse it each time you navigate to it. Although the page will never be released, &lt;strong&gt;this isn&amp;#39;t considered a memory leak&lt;/strong&gt; because the number of stored pages remains constant regardless of how often you navigate to it. This technique is akin to caching and can be useful for frequently accessed pages.&lt;/div&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20242108-MAUI-Memory-Profiling/Singleton%20(not%20a%20leak).jpg" alt="Object staying in memory because of DI" style="max-height:400px;"&gt;&lt;h2&gt;Memory Profiling with .NET Meteor and Heapview&lt;/h2&gt;&lt;p&gt;Since .NET doesn&amp;#39;t document memory leaks,&amp;nbsp;how can we identify objects cluttering memory? &lt;/p&gt;&lt;p&gt;One option is to use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=nromanov.dotnet-meteor" target="_blank"&gt;.NET Meteor&lt;/a&gt; VS Code extension (to capture a memory dump). Once captured, we can&amp;nbsp;visualize the memory dump via&amp;nbsp;&lt;a href="https://github.com/1hub/dotnet-heapview" target="_blank"&gt;Heapview&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Here&amp;#39;s how to configure .NET Meteor to capture a memory dump.&amp;nbsp;&lt;/p&gt;&lt;h3&gt;Step 1: Install Tools&lt;/h3&gt;&lt;p&gt;First, we&amp;#39;ll need to install the appropriate tools:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://code.visualstudio.com/download" target="_blank"&gt;Visual Studio Code&lt;/a&gt;&amp;nbsp;- a&amp;nbsp;lightweight, cross-platform editor that, with the help of a few extensions, provides all the IDE capabilities needed to develop .NET MAUI apps for multiple operating systems.&lt;/li&gt;&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=nromanov.dotnet-meteor" target="_blank"&gt;.NET Meteor&lt;/a&gt;&amp;nbsp;- a VS Code extension for running, debugging, and profiling .NET MAUI projects.&lt;/li&gt;&lt;li&gt;&lt;a href="https://github.com/1hub/dotnet-heapview" target="_blank"&gt;Heapview&lt;/a&gt; -&amp;nbsp;a&amp;nbsp;cross-platform .NET tool for visualizing memory snapshots. To install it, run the following command using the Command Prompt or VS Code Terminal:&lt;br&gt;&lt;pre&gt;&lt;code class="language-cmdline"&gt;dotnet tool install -g dotnet-heapview&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Step 2: Prepare App&lt;/h3&gt;&lt;p&gt;Once we&amp;#39;ve installed the necessary tools, we must open the target project. Since VS Code does not use Visual Studio&amp;nbsp;&lt;code&gt;*.sln&lt;/code&gt; solution files, we&amp;#39;ll need to use the &lt;strong&gt;Open Folder&lt;/strong&gt;&amp;nbsp;menu item and select the project folder (for&amp;nbsp;this blog post, I&amp;#39;ll use the following sample project:&amp;nbsp;&lt;a href="https://github.com/DevExpress-Examples/common-maui-memory-leaks" target="_blank"&gt;Common .NET MAUI Memory Leaks&lt;/a&gt;):&lt;/p&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Open%20Project%20Folder.png" alt="Opening the VS Code .NET MAUI Project" class="small" style="width:401px;height:291px;"&gt;&lt;p&gt;After opening the project folder, we&amp;#39;ll navigate to the &lt;strong&gt;Run and Debug&lt;/strong&gt;&amp;nbsp;tab and create a &lt;code&gt;launch.json&lt;/code&gt; file.&lt;/p&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Launch%20File.png" alt="Creating the Launch File" class="small" style="width:400px;height:274px;"&gt;&lt;p&gt;.NET Meteor uses settings from&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;launch.json&lt;/code&gt; to run, debug, and profile apps. To profile an application, we&amp;#39;ll need to add a configuration entry with the &lt;code&gt;profilerMode&lt;/code&gt; attribute set to &lt;code&gt;gcdump&lt;/code&gt;&lt;br&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-json" data-line="11,14"&gt;{ 
    &amp;quot;version&amp;quot;: &amp;quot;0.2.0&amp;quot;, 
    &amp;quot;configurations&amp;quot;: [ 
        { 
            &amp;quot;name&amp;quot;: &amp;quot;.NET Meteor Debugger&amp;quot;, 
            &amp;quot;type&amp;quot;: &amp;quot;dotnet-meteor.debugger&amp;quot;, 
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;, 
            &amp;quot;preLaunchTask&amp;quot;: &amp;quot;dotnet-meteor: Build&amp;quot; 
        }, 
        { 
            &amp;quot;name&amp;quot;: &amp;quot;.NET Meteor Profiler&amp;quot;, 
            &amp;quot;type&amp;quot;: &amp;quot;dotnet-meteor.debugger&amp;quot;, 
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;, 
            &amp;quot;profilerMode&amp;quot;: &amp;quot;gcdump&amp;quot;, 
            &amp;quot;preLaunchTask&amp;quot;: &amp;quot;dotnet-meteor: Build&amp;quot; 
        } 
    ] 
} &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We&amp;#39;ll now save the modified &lt;code&gt;launch.json&lt;/code&gt; file and select the profiling configuration from the dropdown menu next to the &lt;strong&gt;Start&lt;/strong&gt;&amp;nbsp;button.&lt;/p&gt;&lt;p&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Select%20Profiling%20Configuration.png" alt="Select Profiling Configuration" class="small" style="width:401px;height:284px;"&gt;&lt;/p&gt;&lt;p&gt;Next, we&amp;#39;ll select the device used to run the project:&lt;/p&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20242108-MAUI-Memory-Profiling/Device%20Popup%20in%20VS%20Code.png" alt=""&gt;&lt;h3&gt;Step 3: Obtain a Profiling Snapshot&lt;/h3&gt;&lt;p&gt;We can now run our sample application and collect profiling data (be certain to select &lt;strong&gt;Run Without Debugging&lt;/strong&gt;).&lt;/p&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Run%20Without%20Debugging.png" alt="Run the project without debugging" class="small" style="width:550px;height:291px;"&gt;&lt;p&gt;Before collecting the memory dump, we must invoke the garbage collector&amp;#39;s &lt;code&gt;Collect&lt;/code&gt; and &lt;code&gt;WaitForPendingFinalizers&lt;/code&gt; methods. We&amp;#39;ll need to call these methods multiple times, as garbage collection occurs in several cycles. Note: in your .NET MAUI project, you can create a button for profiling purposes and trigger garbage collection via the &lt;code&gt;Button.Click&lt;/code&gt; event handler:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp"&gt;GC.Collect();
GC.WaitForPendingFinalizers();&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you&amp;#39;re running&amp;nbsp;&lt;a href="https://github.com/DevExpress-Examples/common-maui-memory-leaks" target="_blank"&gt;our GitHub test project&lt;/a&gt;, you can click the green button to invoke these methods.&lt;/p&gt;&lt;p&gt;We can now open the &lt;strong&gt;VS Code Debug Console&lt;/strong&gt; window and execute the &lt;code&gt;/dump&lt;/code&gt; command to generate a memory dump file (which will be added to the project&amp;nbsp;folder). If following along, you should see a message like this:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-cmdline"&gt;Writing gcdump to &amp;#39;...\com.companyname.TypicalMemoryLeaks.gcdump&amp;#39;... 
command handled by DotNet.Meteor.Debug.GCDumpLaunchAgent 
Finished writing 672119 bytes. &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the device port used by .NET Meteor  is busy (and unable to obtain the memory dump), the memory dump won&amp;#39;t be collected.&amp;nbsp;To address the issue, you should modify the&amp;nbsp;&lt;strong&gt;Profiler Host Port&lt;/strong&gt; setting. Navigate to &lt;strong&gt;VS Code Extensions Tab | Extension Settings | Profiler Host Port, &lt;/strong&gt;and make the necessary change:&lt;/p&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20242108-MAUI-Memory-Profiling/Meteor%20Profiler%20Host%20Port.png" alt="Debugging host port in .NET Meteor"&gt;&lt;h3&gt;Step 4: Analyze Snapshot&lt;/h3&gt;&lt;p&gt;The memory dump should now be in the project folder. To analyze it with Heapview, we&amp;#39;ll open a new Terminal window in VS Code (&lt;strong&gt;Terminal | New Terminal&lt;/strong&gt;) and execute the &lt;code&gt;dotnet-heapview&lt;/code&gt; command with the memory dump file name as a parameter:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-cmdline"&gt;dotnet-heapview com.companyname.TypicalMemoryLeaks.gcdump&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will open the following in Heapview:&amp;nbsp;&lt;/p&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20242108-MAUI-Memory-Profiling/Heapview%20.NET%20MAUI%20memory%20dump.png" alt="Heampview .NET MAUI memory dump" style="width:893px;height:606px;"&gt;&lt;ol&gt;&lt;li&gt;&lt;em&gt;Types of objects currently held in memory.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Instances of these objects in memory.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Number of child items held by the current object.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Chain&amp;nbsp;of elements that prevent the selected object from being released.&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;In this example, the page named &lt;code&gt;DirectReferenceLeakPage&lt;/code&gt; &lt;strong&gt;(1)&lt;/strong&gt; has three active instances &lt;strong&gt;(2)&lt;/strong&gt; and seventeen references to child objects &lt;strong&gt;(3)&lt;/strong&gt;. In the Retainers panel, note&amp;nbsp;that &lt;code&gt;DirectReferenceLeakPage&lt;/code&gt; is part of a list of &lt;code&gt;ContentPages&lt;/code&gt; in the &lt;code&gt;AppShell&lt;/code&gt; object &lt;strong&gt;(4)&lt;/strong&gt;. Since &lt;code&gt;AppShell&lt;/code&gt; persists throughout the application&amp;#39;s lifecycle, it will never be released. To fix the leak, we need to remove &lt;code&gt;DirectReferenceLeakPage&lt;/code&gt; from &lt;code&gt;AppShell&lt;/code&gt;&amp;nbsp;references.&lt;/p&gt;&lt;p&gt;We&amp;#39;ll address this particular memory leak by removing the reference to &lt;code&gt;DirectReferenceLeakPage&lt;/code&gt;&amp;nbsp;in the &lt;code&gt;OnDisappearing&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;event handler:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp"&gt;private void OnDisappearing(object sender, EventArgs e)
{
    ((AppShell)App.Current.MainPage).OpenedChildPages.Remove(this);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once the leak is fixed, we can collect the memory dump once again and&amp;nbsp;open it in Helpview. Notice that&amp;nbsp;&lt;span&gt;&lt;code&gt;DirectReferenceLeakPage&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;can no longer be found in the retained objects view:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20242108-MAUI-Memory-Profiling/Heapview%20-%20no%20leak.png" alt="Heapview with a fixed memory leak"&gt;&lt;/p&gt;&lt;h2&gt;Summary&lt;/h2&gt;&lt;p&gt;Needless to say, identifying the source of a memory leak can be challenging. .NET Meteor and Heapview&amp;nbsp;can help you isolate unreleased objects&amp;nbsp;and trace associated references (crucial for diagnosing both common and atypical&amp;nbsp;memory-related issues).&lt;/p&gt;&lt;p&gt;If you are new to .NET MAUI or want to optimize an existing .NET MAUI project, be sure to review the following blog post:&amp;nbsp;&amp;nbsp;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2024/04/01/How-to-Profile-NET-MAUI-Applications-and-Isolate-Performance-Related-Issues.aspx"&gt;How to Profile .NET MAUI Applications and Isolate Performance-Related Issues&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 04 Nov 2024 23:05:00 Z</pubDate>
      <dc:creator>Alexander Russkov (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388198</guid>
      <link>https://community.devexpress.com/Blogs/mobile/archive/2024/10/01/net-maui-check-grammar-within-the-devexpress-html-edit-using-openai-gpt-models.aspx</link>
      <category domain="https://community.devexpress.com/Tags/2024">2024</category>
      <category domain="https://community.devexpress.com/Tags/AI">AI</category>
      <category domain="https://community.devexpress.com/Tags/Android">Android</category>
      <category domain="https://community.devexpress.com/Tags/iOS">iOS</category>
      <category domain="https://community.devexpress.com/Tags/maui">maui</category>
      <category domain="https://community.devexpress.com/Tags/mobile">mobile</category>
      <title>.NET MAUI: Check Grammar within the DevExpress HTML Edit Using OpenAI GPT Models</title>
      <description>&lt;p&gt;Back in school, I dreamed of a magic pen that could fix all my mistakes and come up with creative ways to describe fictional characters. With AI, the magic pen is finally here.&lt;/p&gt;&lt;p&gt; As you know, developers are discovering numerous ways to add AI to their solutions (and it’s often easier than you’d think) thanks to easy-to-use cloud-based AI services and flexible control APIs. In this blog post, I&amp;#39;ll use OpenAI to extend the capabilities of the DevExpress&amp;nbsp;&lt;a href="https://docs.devexpress.com/MAUI/404635/html-edit/html-edit"&gt;.NET MAUI HTML Edit&lt;/a&gt;. Specifically, I&amp;#39;ll show you how easy it is to add&amp;nbsp;AI-related capabilities to our HTML Edit Control and tweak its UI for the best possible user experience.&lt;/p&gt;


&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:4%;margin:0px 0px 0px 0px;"&gt;
&lt;img src="https://community.devexpress.com/blogs/mobile/202422709-AI-With-Html-Edit/html-edit-ai-assistant.png" alt="AI Assistant in HTML Edit" width="40%"&gt;
&lt;/div&gt;

&lt;p&gt;
    &lt;a href="https://github.com/DevExpress-Examples/maui-html-edit/tree/24.1.3%2B/CS/AIAssistant" class="Button Gray"&gt;GitHub Example&lt;/a&gt; 
&lt;/p&gt;

&lt;h2&gt;Configure OpenAI&lt;/h2&gt;

&lt;p&gt;Until recently, only companies with dedicated machine learning experts were in position to add&amp;nbsp;advanced AI features to their products. Today, thanks to powerful pretrained models with billions of parameters, leveraging AI&amp;nbsp;requires minimal effort. Cloud services like OpenAI now make it easy to tackle complex business requirements, such as:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Text generation: The core feature of ChatGPT, which we&amp;#39;ll use in this post.&lt;/li&gt;
    &lt;li&gt;Image analysis: Detect objects in images, identify boundaries, and more&lt;/li&gt;
	&lt;li&gt;Image generation: Create images from text descriptions—ideal for apps with design features or data visualization needs&lt;/li&gt;
	&lt;li&gt;Text-to-speech and speech-to-text: Seamlessly convert between spoken and written languages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The process is even more straightforward with the OpenAI .NET library since it provides&amp;nbsp;cloud APIs without directly handling HTTP requests. To get started with OpenAI, you will need to:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://platform.openai.com/signup"&gt;Sign up for OpenAI&lt;/a&gt; if you don&amp;#39;t already have an account.&lt;/li&gt;
&lt;li&gt;Visit the &lt;a href="https://platform.openai.com/api-keys"&gt;API Keys&lt;/a&gt; page to obtain your API key. Remember, OpenAI uses a credit system to monetize the service—the more powerful the model, the higher the cost. New accounts typically receive free credits unless you&amp;#39;ve created one previously.&lt;/li&gt;
&lt;li&gt;Open your .NET MAUI project and reference the &lt;a href="https://www.nuget.org/packages/OpenAI/"&gt;OpenAI NuGet package&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a ChatClient instance and pass your API key to the constructor:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp"&gt;ChatClient aiClient = new(model: &amp;quot;gpt-3.5-turbo&amp;quot;, &amp;quot;YOUR API TOKEN&amp;quot;);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We&amp;#39;ll use the GPT 3.5 Turbo model as it&amp;#39;s less resource-intensive, but you can always switch to a more powerful model for more complex requirements.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Configure DevExpress Components&lt;/h2&gt;

&lt;p&gt;To fully leverage AI, it&amp;#39;s essential to create an intuitive user interface. When handling large text messages, it&amp;#39;s helpful to support rich text formatting (lists, bold, headings) to visually separate text&amp;nbsp;blocks. Accordingly, we&amp;#39;ll use our .NET MAUI HTML Editor.&amp;nbsp; Its&amp;nbsp;APIs allow&amp;nbsp;you to load documents from various sources and retrieve current HTML content (to&amp;nbsp;send to OpenAI). We&amp;#39;ll also incorporate buttons to trigger AI actions, using the &lt;a href="https://docs.devexpress.com/MAUI/404604/dialogs-menu-and-navigation/toolbar/toolbar-overview"&gt;Toolbar&lt;/a&gt; control (which is designed to work seamlessly with components like the DevExpress .NET MAUI HTML Editor).&lt;/p&gt;

&lt;h3&gt;
    Display a Document in the HTML Edit Control
&lt;/h3&gt;

&lt;p&gt;With our .NET MAUI HTML Editor, you can load content from various sources like files, streams, strings, or URIs. For this example, we&amp;#39;ll load HTML from a document stored in the application&amp;#39;s bundle (in the Resources\Raw folder). To display the HTML, simply read the file and pass it to the HTML Editor&amp;#39;s &lt;a href="https://docs.devexpress.com/MAUI/404637/html-edit/load-and-obtain-markup#display-content-asynchronous"&gt;SetHtmlSourceAsync&lt;/a&gt; method:
&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;async void OnPageAppearing(object sender, EventArgs e) {
   using Stream stream = await FileSystem.Current.OpenAppPackageFileAsync(&amp;quot;mail.html&amp;quot;);
   using StreamReader reader = new StreamReader(stream);
   await htmledit.SetHtmlSourceAsync(await reader.ReadToEndAsync());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;
    Add a Custom Toolbar
&lt;/h3&gt;
&lt;p&gt;
    On smaller mobile screens, incorporating multiple action buttons without compromising usability can be challenging. It&amp;#39;s crucial to strike a&amp;nbsp;balance between the number of actionable elements and their size. Additionally, you need to decide which elements to display since in many instances, you don’t need to display all actions simultaneously (as this can clutter the UI).
&lt;/p&gt;
&lt;p&gt;
    Our Toolbar control can help address these realities:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;It automatically adjusts elements based on&amp;nbsp;Material Design 3 standards, so you don’t have to worry about padding or sizing.&lt;/li&gt;
	&lt;li&gt;It allows you to group elements into pages. Said differently, you can display all AI-related actions on a separate page, displayed only when needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
    The HTML Editor includes a built-in toolbar, but we’ll hide it in favor of our custom toolbar. To do this, set the HTML Editor’s &lt;a href="https://docs.devexpress.com/MAUI/404639/html-edit/toolbar#define-a-custom-toolbar-in-xaml"&gt;ShowToolbar&lt;/a&gt; property to false and create a Toolbar control with appropriate&amp;nbsp;custom buttons:
&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;dx:SafeKeyboardAreaView&amp;gt;
	&amp;lt;Grid RowDefinitions=&amp;quot;*,Auto&amp;quot;&amp;gt;
		&amp;lt;dx:HtmlEdit x:Name=&amp;quot;htmledit&amp;quot; ShowToolbar=&amp;quot;false&amp;quot; dx:DXDockLayout.Dock=&amp;quot;Top&amp;quot;/&amp;gt;
		&amp;lt;dx:DXToolbar Grid.Row=&amp;quot;1&amp;quot;&amp;gt;
			&amp;lt;dx:ToolbarNavigationButton Content=&amp;quot;🪄&amp;quot; PageName=&amp;quot;AIAssistant&amp;quot;/&amp;gt;
			&amp;lt;dx:ToolbarPage Name=&amp;quot;AIAssistant&amp;quot; ShowBackButton=&amp;quot;true&amp;quot;&amp;gt;
				&amp;lt;dx:ToolbarButton Content=&amp;quot;Fix Grammar ✨&amp;quot; Clicked=&amp;quot;OnFixGrammarClick&amp;quot;/&amp;gt;
				&amp;lt;dx:ToolbarButton Content=&amp;quot;Translate to German 🇩🇪&amp;quot; Clicked=&amp;quot;OnToGermanClick&amp;quot;/&amp;gt;
				&amp;lt;dx:ToolbarButton Content=&amp;quot;Enhance 🪄&amp;quot; Clicked=&amp;quot;OnEnhanceClick&amp;quot;/&amp;gt;
            &amp;lt;/dx:ToolbarPage&amp;gt;
		&amp;lt;/dx:DXToolbar&amp;gt;
	&amp;lt;/Grid&amp;gt;
&amp;lt;/dx:SafeKeyboardAreaView&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
    As you&amp;#39;ll notice, we&amp;#39;ve placed the HTML Editor and Toolbar inside the &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Core.SafeKeyboardAreaView"&gt;SafeKeyboardAreaView&lt;/a&gt; container to prevent overlap when the keyboard is opened.
&lt;/p&gt;

&lt;h3&gt;
    Obtain an AI Response and Display it within our .NET MAUI HTML Editor&lt;/h3&gt;
&lt;p&gt;
    Once your custom toolbar buttons are set up, you can handle associated click events. When a button is clicked, we’ll retrieve content from the HTML Editor, send it to OpenAI, and display the response back in the DevExpress .NET MAUI HTML Editor.
&lt;/p&gt;
&lt;p&gt;
    To obtain&amp;nbsp;HTML content, we’ll use the &lt;a href="https://docs.devexpress.com/MAUI/404637/html-edit/load-and-obtain-markup#retrieve-the-displayed-content"&gt;GetHtmlAsync&lt;/a&gt; method. We&amp;#39;ll then call the CompleteChatAsync method from the OpenAI client class we configured earlier. Finally, we’ll assign the response from OpenAI to the HTML Editor:
&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp" data-line="7-11"&gt;async void OnFixGrammarClick(System.Object sender, System.EventArgs e) {
	await ExecuteChatRequest($&amp;quot;Fix grammar errors:{await htmledit.GetHtmlAsync()}&amp;quot;);
}
 
async Task ExecuteChatRequest(string prompt) {
	try {
		ChatCompletion completion = await aiClient.CompleteChatAsync(new List&amp;lt;ChatMessage&amp;gt; {
		    new SystemChatMessage($&amp;quot;You are an assistant correcting HTML text. Use only those tag types that you can find in the source document&amp;quot;),
		    new UserChatMessage(prompt)
		});
		await htmledit.SetHtmlSourceAsync(completion.Content[0].Text);
	}
	catch (Exception ex) {
	    await Shell.Current.DisplayAlert(&amp;quot;Error&amp;quot;, ex.Message, &amp;quot;OK&amp;quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    The CompleteChatAsync method accepts a list of chat messages, which can be one of the following:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;System: A general instruction for the model. You can define only one system message.&lt;/li&gt;
    &lt;li&gt;User: The user’s prompt, which can include additional instructions and content for the model to process.&lt;/li&gt;
    &lt;li&gt;Assistant: The model&amp;#39;s reply. You can combine multiple user and assistant messages to build a chat history, ensuring the latest request includes all previous context.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Summary
&lt;/h2&gt;
&lt;p&gt;
As user/business expectations continue to rise, integrating AI capabilities will become a more and more critical. Fortunately, you don’t need to be a machine learning expert to take advantage of AI. In this post, I followed these simple steps to incorporate intelligent text enhancements into my .NET MAUI project:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sign&amp;nbsp;up for OpenAI and obtain an API key.&lt;/li&gt;
&lt;li&gt;Add a library to your client that connects to OpenAI services.&lt;/li&gt;
&lt;li&gt;Retrieve content from the DevExpress .NET MAUI HTML Editor using &lt;a href="https://docs.devexpress.com/MAUI/404637/html-edit/load-and-obtain-markup#retrieve-the-displayed-content"&gt;GetHtmlAsync&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add toolbar buttons to invoke AI functions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
These easy-to-follow steps can address a variety of requirements -&amp;nbsp;making the dream of a &amp;quot;magic pen&amp;quot; a reality.
&lt;/p&gt;</description>
      <pubDate>Tue, 01 Oct 2024 00:00:00 Z</pubDate>
      <dc:creator>Anthony Sameishchev (DevExpress)</dc:creator>
      <dx:excerpt>Back in school, I dreamed of a magic pen that could fix all my mistakes and come up with creative ways to describe fictional characters. With AI, the magic pen is finally here.</dx:excerpt>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388192</guid>
      <link>https://community.devexpress.com/Blogs/mobile/archive/2024/09/23/net-maui-early-access-preview-v24-2-amp-minor-update-enhancements-v24-1-5.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.net+maui">.net maui</category>
      <category domain="https://community.devexpress.com/Tags/Android">Android</category>
      <category domain="https://community.devexpress.com/Tags/EAP">EAP</category>
      <category domain="https://community.devexpress.com/Tags/iOS">iOS</category>
      <category domain="https://community.devexpress.com/Tags/maui">maui</category>
      <category domain="https://community.devexpress.com/Tags/prerelease">prerelease</category>
      <category domain="https://community.devexpress.com/Tags/v24.2">v24.2</category>
      <title>.NET MAUI — Early Access Preview (v24.2) &amp; Minor Update Enhancements (v24.1.5) </title>
      <description>&lt;div&gt;In this blog post, I’ll outline  enhancements available in our early access preview (EAP v24.2) build. The post includes new features we expect to ship in our next major release (v24.2) and enhancements  made&amp;nbsp;in  official minor updates (v24.1.4,&amp;nbsp;v24.1.5).&lt;/div&gt;&lt;h2&gt;Early Access Preview (v24.2)&lt;/h2&gt;&lt;div&gt;To download/install our EAP,&amp;nbsp;check “&lt;em&gt;Include prerelease&lt;/em&gt;” when using the&amp;nbsp;&lt;a href="https://nuget.devexpress.com/" target="_blank"&gt;DevExpress NuGet feed&lt;/a&gt;:&lt;/div&gt;&lt;p&gt;&lt;img src="https://community.devexpress.com/blogs/mobile/20241309-maui-eap-24-2/Prerelease%20MAUI%20NuGet.png" alt=""&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;div&gt;&lt;div class="Note"&gt;&lt;div&gt;Early Access and CTP builds are provided solely for early testing purposes and are not ready for production use. This build can be installed side by side with other major versions of DevExpress products. Please back up your project and other important data before installing Early Access and CTP builds.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;This EAP may not include all features/products we expect to ship in our v24.2 release cycle. As its name implies, the EAP offers an early preview of what we expect to ship in two months.&amp;nbsp;For additional information on what you can expect, refer to our&amp;nbsp;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2024/07/12/net-maui-year-end-roadmap-v24-2.aspx" target="_blank"&gt;Year-End 2024.2 Roadmap&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3&gt;Ease of Use and IDE Integration&lt;/h3&gt;&lt;p&gt;How long does it take to go from a blank page to a fully functional view? While the amount of&amp;nbsp;time varies by project, the process typically involves the following  steps: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Designing a mockup&lt;/li&gt;&lt;li&gt;Selecting appropriate UI components&lt;/li&gt;&lt;li&gt;Setting up control APIs&lt;/li&gt;&lt;li&gt;Implementing a view model to interact with business logic&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;And of course, each of these steps can be broken down into smaller tasks. &lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;One of our primary goals for the upcoming major update (v24.2) is to streamline this entire process - helping you deliver intuitive mobile apps in the shortest possible time.&amp;nbsp;&lt;/div&gt;&lt;div&gt;To make this happen, we&amp;#39;re introducing new project templates that include&amp;nbsp;popular&amp;nbsp;modules and pre-designed pages. While these templates &lt;strong&gt;aren&amp;#39;t available in the current EAP release&lt;/strong&gt;, I’d like to share our prototype with you...&lt;/div&gt;&lt;p&gt;&lt;video autoplay="true" loop="true" muted="true" style="width:936px;"&gt;
&lt;source src="https://community.devexpress.com/blogs/mobile/20241309-maui-eap-24-2/MAUI%20Wizard%20prototype%20EAP.mov" type="video/mp4"&gt;
&lt;/video&gt;&lt;/p&gt;&lt;p&gt;In addition to templates, we&amp;#39;re planning to introduce a toolbox packed with predefined XAML blocks, allowing you to design views by  dragging items from the toolbox.&lt;/p&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20241309-maui-eap-24-2/Toolbox%20Prototype.png" alt=""&gt;&lt;div&gt;We understand that every app has unique requirements&amp;nbsp;and predefined templates can&amp;#39;t address&amp;nbsp;each and every usage scenario. That&amp;#39;s why we&amp;#39;ve made our building blocks flexible - use them as a foundation and customize them  to suit your specific needs.&lt;/div&gt;&lt;h3&gt;MVVM&lt;/h3&gt;&lt;div&gt; We&amp;#39;ve developed a library of services, helpers, and markup extensions to make it easier&amp;nbsp;to create MVVM-based applications. We didn’t create our own MVVM framework (as we did for WPF and WinForms components).&amp;nbsp;Instead, we went with the&amp;nbsp;&lt;a href="https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/" target="_blank"&gt;Community Toolkit MVVM&lt;/a&gt;. Our library doesn’t replace it but enhances it with additional functionality.&lt;/div&gt;&lt;h4&gt;Services&lt;/h4&gt;&lt;p&gt;The following is a list of services&amp;nbsp;our MVVM library includes: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;&lt;span&gt;NavigationService&lt;/span&gt;&lt;/code&gt;&lt;span&gt;.&lt;/span&gt; Navigate between pages directly from your view model.&lt;/li&gt;&lt;li&gt;&lt;code&gt;PrintService&lt;/code&gt;&lt;span&gt;.&amp;nbsp;&lt;/span&gt;Launch the default print dialog to print files.&lt;/li&gt;&lt;li&gt;&lt;code&gt;SaveFilePicker&lt;/code&gt;&lt;span&gt;.&lt;/span&gt; Open a dialog and allow&amp;nbsp;users to save a file.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;These services are registered in the default Dependency Injection (DI) container. You simply need to register your view model and define a constructor that accepts corresponding&amp;nbsp;interfaces to access the service within your view model.&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;code class="language-csharp" data-line="3-5"&gt;public class ViewModel 
{ 
    public ViewModel(INavigationService navigationService, 
                     IPrintService printService, 
                     ISaveFilePicker saveFilePickerService) 
    { 
        //navigationService.GoToAsync(...); 
        //printService.PrintAsync(...); 
        //saveFilePickerService.SaveAsync(...); 
    } 
} &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you prefer to use your own custom service implementation, you can register it in the DI container to override the default registration:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp" data-line="6"&gt;public static class MauiProgram 
{ 
    public static MauiApp CreateMauiApp() 
    { 
        //... 
        builder.Services.AddSingleton&amp;lt;INavigationService, NavigationServiceEx&amp;gt;(); 
    } 
} 
public class NavigationServiceEx : NavigationService { }&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;We&amp;#39;ve also implemented a UI service mechanism that allows you to interact with UI objects directly from your view model - without tying your code to a specific element type.&lt;/div&gt;&lt;div&gt;For instance, to force a CollectionView scroll to the last element, you can create a custom service that calls&amp;nbsp;&lt;code&gt;DXCollectionView.ScrollTo&lt;/code&gt;:&lt;/div&gt;&lt;pre&gt;&lt;code class="language-csharp"&gt;public interface IScollService  {  
    void ScrollToEnd();  
} 
public class ScollService : UIServiceBase, IScollService 
{ 
    public void ScrollToEnd() 
    { 
        DXCollectionView collection = (DXCollectionView)AssociatedObject; 
        collection.ScrollTo(collection.VisibleItemCount, DXScrollToPosition.End); 
    } 
} &lt;/code&gt;&lt;/pre&gt;&lt;div&gt;Once complete, you can attach this service to your &lt;code&gt;DXCollectionView&lt;/code&gt;&lt;span&gt;:&lt;/span&gt; &lt;/div&gt;&lt;pre&gt;&lt;code class="language-xml" data-line="3"&gt;&amp;lt;dx:DXCollectionView&amp;gt; 
    &amp;lt;dx:DXCollectionView.Behaviors&amp;gt; 
        &amp;lt;local:ScollService/&amp;gt; 
    &amp;lt;/dx:DXCollectionView.Behaviors&amp;gt; 
&amp;lt;/dx:DXCollectionView &amp;gt; &lt;/code&gt;&lt;/pre&gt;In your view model, you can access the registered service via the service container and trigger UI-related actions through the service interface: &lt;pre&gt;&lt;code class="language-csharp" data-line="8"&gt;public partial class ViewModel : IUIServiceClient 
{ 
    public IUIServiceContainer ServiceContainer { get; } = new UIServiceContainer(); 
  
    void ShowLastItem() 
    { 
        var scrollService = ServiceContainer.GetRequiredService&amp;lt;IScollService&amp;gt;(); 
        scrollService.ScrollToEnd(); 
    } 
} &lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;This technique allows you to invoke UI actions in a clean, MVVM-compliant manner.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;h4&gt;Dependency Injection&lt;/h4&gt;&lt;p&gt;&lt;span&gt;To simplify Dependency Injection, we&amp;#39;ve created a markup extension that allows you to assign a view model from the DI container directly in XAML:&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;pre&gt;&lt;code class="language-xml" data-line="3"&gt;&amp;lt;ContentPage ... 
             xmlns:dx=&amp;quot;http://schemas.devexpress.com/maui&amp;quot; 
             BindingContext=&amp;quot;{dx:Ioc Type={x:Type vm:MainViewModel}}&amp;quot;&amp;gt; &lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class="language-csharp" data-line="4"&gt;    public static class MauiProgram  { 
       public static MauiApp CreateMauiApp()   { 
           //... 
           builder.Services.AddTransient&amp;lt;ViewModel&amp;gt;(); 
       } 
  } &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;With this extension, &lt;/span&gt;&lt;span&gt;there&amp;#39;s&lt;/span&gt;&lt;span&gt; no need to create a constructor in your view to pass the view model and manually assign it to&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;BindingContext&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp"&gt;//not required anymore
public MainPage(ViewModel viewModel) 
{ 
	BindingContext = viewModel; 
	InitializeComponent(); 
} &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;Ioc&lt;/code&gt; extension allows you to inject a view model into a view, even if the view itself isn&amp;#39;t registered in the DI container. This will be useful when you have a&amp;nbsp;&amp;nbsp;&lt;code&gt;ContentView&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;embedded within a parent page in XAML. &lt;br&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-xml" data-line="3, 9"&gt;&amp;lt;ContentPage ...  
           x:Class=&amp;quot;MauiExample.MainPage&amp;quot; &amp;gt; 
           &amp;lt;views:ChildContentView/&amp;gt; 
          &amp;lt;!--...--&amp;gt; 
&amp;lt;/ContentPage&amp;gt; 
 
&amp;lt;ContentView ... 
             x:Class=&amp;quot; MauiExample.ChildContentView&amp;quot; 
             BindingContext=&amp;quot;{dx:Ioc Type={x:Type vm:ChildViewModel}}&amp;quot;&amp;gt; 
    &amp;lt;!--...--&amp;gt; 
&amp;lt;/ContentView&amp;gt; &lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Collection View – Frozen Group Row&lt;/h3&gt;&lt;p&gt;You can now keep group row headers visible while scrolling, as long as at least one child row in the group is on screen. Enable the &lt;code&gt;DXCollectionView.AllowFixedGroupHeaders&lt;/code&gt;&amp;nbsp;option to incorporate this feature in your DevExpress-powered .NET MAUI app.&amp;nbsp;&lt;/p&gt;&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:10px;margin:0px 0px 0px 0px;"&gt;&lt;img src="https://community.devexpress.com/blogs/mobile/20240715-MAUI-EAP-24-2/24.2-eap-cv-freeze-group-header@2x.gif" alt=""&gt;
&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;Asynchronous CRUD&lt;/h3&gt;&lt;p&gt;  As you  know, both our .NET MAUI Collection View and .NET MAUI Data Grid controls include&amp;nbsp;&lt;a href="https://docs.devexpress.com/MAUI/404421/collection-view/crud/crud-overview" target="_blank"&gt;CRUD APIs&lt;/a&gt;&amp;nbsp;to help you create detail and edit item forms. Since mobile apps often need to connect to remote services for data editing purposes, we&amp;#39;ve enhanced our CRUD APIs to support asynchronous operations. &lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;video width="936" height="700" autoplay="true" loop="true" muted="true" style="width:936px;"&gt;
&lt;source src="https://community.devexpress.com/blogs/mobile/20241309-maui-eap-24-2/24.2-AsyncCRUD-a.mp4" type="video/mp4"&gt;
&lt;/video&gt;&lt;/p&gt;&lt;p&gt;Both the Collection View and Data Grid use CRUD view models to automatically transfer information between detail/edit views and handle actions like edit, save, and delete operations. We&amp;#39;ve made these commands asynchronous, so  you can now execute them without freezing the UI. Additionally, we&amp;#39;ve added an&amp;nbsp;&lt;code&gt;&lt;span&gt;IsAsyncOperationInProgress&lt;/span&gt;&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;property. This property allows you to&amp;nbsp;display a loading indicator during asynchronous operations.&lt;/p&gt;&lt;h3&gt;Data Grid Multi Selection&lt;/h3&gt;&lt;p&gt;  You can now enable multiple row selection in our Data Grid. Simply set&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;DataGridView.SelectionMode&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;to&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;Multiple&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;to activate this feature.   &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:10px;margin:0px 0px 0px 0px;"&gt;
    &lt;img src="https://community.devexpress.com/blogs/mobile/20241309-maui-eap-24-2/24.2-MultipleSelection-a.png" width="50%" alt=""&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;To retrieve selected rows in your view model, bind&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;DataGridView.SelectedItems&lt;/code&gt;&amp;nbsp;to a &lt;code&gt;ObservableCollection&amp;lt;T&amp;gt;&lt;/code&gt;&amp;nbsp;property type.&lt;/p&gt;&lt;h2&gt;Minor Update (v24.1)&lt;/h2&gt;&lt;p&gt; The following is a quick overview of  new features included in  recent minor updates. These features are&amp;nbsp;included in our official releases, so you can start using them immediately by updating your NuGet packages to the most recent&amp;nbsp;version.&lt;/p&gt;&lt;h3&gt;Collection View &amp;amp; Tree View –  Header &amp;amp; Footer&lt;/h3&gt;&lt;p&gt;   Headers and footers allow you to add custom elements above and below list items. Since&amp;nbsp;they scroll alongside&amp;nbsp;the rest of the view, this new feature helps make&amp;nbsp;efficient use of available screen space. You can define any content for your&amp;nbsp;header/footer (display elements that stand out from the rest of the list).&lt;/p&gt;&lt;video width="936" height="700" autoplay="true" loop="true" muted="true" style="width:936px;"&gt;
&lt;source src="https://community.devexpress.com/blogs/mobile/20241309-maui-eap-24-2/24.2-HeaderFooter-a.mp4" type="video/mp4"&gt;
&lt;/video&gt;&lt;p&gt;Here are a few ways to use headers and footers: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Display favorite items at the top.&lt;/li&gt;&lt;li&gt;Add a collection title.&lt;/li&gt;&lt;li&gt;Include a button to add more items or display the full list.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Related APIs: &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.Header" target="_blank"&gt;Header&lt;/a&gt;, &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.HeaderTemplate" target="_blank"&gt;HeaderTemplate&lt;/a&gt;, &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ShowHeader" target="_blank"&gt;ShowHeader&lt;/a&gt;, &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.Footer" target="_blank"&gt;Footer&lt;/a&gt;, &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.FooterTemplate" target="_blank"&gt;FooterTemplate&lt;/a&gt;, &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ShowFooter" target="_blank"&gt;ShowFooter&lt;/a&gt;&lt;/div&gt;&lt;h3&gt;Collection View &amp;amp; Data Grid – Unlimited Height&lt;/h3&gt;&lt;div&gt;When displaying a small collection within a scrollable layout, you might need to disable virtualization to ensure the collection takes up the  space occupied by its items. This allows you to combine CollectionView with other elements inside a ScrollView, using  one vertical scrollbar. We&amp;#39;ve introduced a new property to disable virtualization in CollectionView, allowing it to expand based on its child items.&lt;/div&gt;&lt;div&gt;Use the  &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ReduceSizeToContent" target="_blank"&gt;ReduceSizeToContent&lt;/a&gt; property to enable this feature.&lt;/div&gt;&lt;h3&gt;Data Grid Immediate Posting&lt;/h3&gt;&lt;div&gt;In earlier versions, Data Grid cell data was only posted to the source after the active editor was closed. While this is what you expect when working with&amp;nbsp;text fields, you may prefer to post changes immediately in other column types (such as&amp;nbsp;CheckBox columns). To address this requirement, we&amp;#39;ve introduced an option that updates the data source instantly when a cell is modified by a user.&lt;/div&gt;&lt;div&gt;To enable this mode, set &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.DataGrid.GridColumn.EnableImmediatePosting" target="_blank"&gt;EnableImmediatePosting&lt;/a&gt; to true. &lt;/div&gt;&lt;h3 id=""&gt;PDF Viewer Print Command&lt;/h3&gt;&lt;p&gt;We implemented a class to invoke native device printing dialogs. This feature is accessible via a built-in toolbar item in our .NET MAUI PDF Viewer control (or directly in code).&lt;/p&gt;&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:10px;margin:0px 0px 0px 0px;"&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20241309-maui-eap-24-2/24.2-eap-pdf-printing.png" width="50%" alt=""&gt;
&lt;/div&gt;&lt;p&gt;To invoke the dialog in code, call &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Pdf.PdfViewer.PrintDocumentAsync(System.String)" target="_blank"&gt;PdfViewer.PrintDocumentAsync&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Optimized Property Initialization&lt;/h3&gt;&lt;div&gt;We’ve reduced the time needed to initialize controls before  first use.&amp;nbsp;&lt;/div&gt;&lt;div&gt;Note: The following chart displays the time required for control initialization, not  overall application startup or view opening time.&lt;/div&gt;&lt;p&gt;&lt;img src="https://community.devexpress.com/blogs/mobile/20241309-maui-eap-24-2/_Component%20Init%20Time.png" alt=""&gt;&lt;/p&gt;&lt;h3&gt;Chat Control Example&lt;/h3&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:10px;margin:0px 0px 0px 0px;"&gt;&lt;img src="https://community.devexpress.com:443/blogs/mobile/20241309-maui-eap-24-2/chat-example.png" width="50%" alt=""&gt;
&lt;/div&gt;&lt;div&gt;&lt;span&gt;Our .NET MAUI Chat example is based on the DevExpress .NET MAUI CollectionView and includes the following options/capabilities:&lt;/span&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Chat-inspired custom&amp;nbsp;styled visual&amp;nbsp;elements&amp;nbsp;(DXCollectionView, TextEdit,&amp;nbsp;DXButton).&lt;/li&gt;&lt;li&gt;Buttons for quick responses.&lt;/li&gt;&lt;li&gt;A fully-functional view model and basic business logic.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;You can download the example from the following GitHub repository: &lt;a href="https://github.com/DevExpress-Examples/maui-chat-app" target="_blank"&gt;Use DevExpress .NET MAUI Components to Build a Chat View&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;h2 id="feedback"&gt;Your Feedback Matters&lt;/h2&gt;&lt;div data-survey-id="f20d8f5e-637d-46aa-95af-66a946d79591" data-survey-auth-required="false"&gt;&lt;/div&gt;</description>
      <pubDate>Mon, 23 Sep 2024 23:00:00 Z</pubDate>
      <dc:creator>Alexander Russkov (DevExpress)</dc:creator>
      <dx:excerpt>In this blog post, I’ll outline enhancements available in our early access preview (EAP v24.2) build. The post includes new features we expect to ship in our next major release (v24.2) and enhancements made in official minor updates (v24.1.4, v24.1.5).</dx:excerpt>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388169</guid>
      <link>https://community.devexpress.com/Blogs/mobile/archive/2024/07/12/net-maui-year-end-roadmap-v24-2.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.net+maui">.net maui</category>
      <category domain="https://community.devexpress.com/Tags/2024">2024</category>
      <category domain="https://community.devexpress.com/Tags/Android">Android</category>
      <category domain="https://community.devexpress.com/Tags/EAP">EAP</category>
      <category domain="https://community.devexpress.com/Tags/iOS">iOS</category>
      <category domain="https://community.devexpress.com/Tags/mobile">mobile</category>
      <category domain="https://community.devexpress.com/Tags/prerelease">prerelease</category>
      <category domain="https://community.devexpress.com/Tags/Roadmap">Roadmap</category>
      <category domain="https://community.devexpress.com/Tags/v24.2">v24.2</category>
      <title>.NET MAUI — Year-End Roadmap (v24.2) </title>
      <description>&lt;p&gt;Thank you for your continued interest in our &lt;a href="https://www.devexpress.com/maui/" target="_blank" rel="noreferrer noopener"&gt;.NET MAUI&lt;/a&gt; component suite. In this post, we&amp;#39;ll share our release plans for .NET MAUI in the second half of 2024 (v24.2). If you have any questions about the features/capabilities mentioned in this roadmap, please leave a comment in the survey below. As always, we appreciate your input.&lt;/p&gt;

&lt;div class="Note"&gt;The information contained within this blog post details our current/projected development plans. Please note that this information is being shared for INFORMATIONAL PURPOSES ONLY and does not represent a binding commitment on the part of Developer Express Inc. This roadmap and the features/products listed within it are subject to change. You should not rely on or use this information to help make a purchase decision about Developer Express Inc products.&lt;/div&gt;

&lt;h2&gt;Ease of Use and IDE Integration&lt;/h2&gt;

&lt;p&gt;Among our primary goals is to help customers develop high-impact applications more efficiently (high impact =&amp;nbsp;performance, reliability, intuitive UX,&amp;nbsp;visual appeal, and scalability). Achieving these qualities requires careful use of platform features and a robust application architecture.&lt;/p&gt;

&lt;p&gt;To streamline this process, we expect to ship pre-built&amp;nbsp;application modules, pages, and templates in our upcoming major release. These resources will simplify&amp;nbsp;component use and ensure your&amp;nbsp;applications are built atop a&amp;nbsp;solid architecture, with well-designed views and optimized performance.&lt;/p&gt;

&lt;h3&gt;New Project Templates&lt;/h3&gt;

&lt;p&gt;We expect to release&amp;nbsp;customizable project templates in our v24.2 release cycle (expected Dec 2024). With the following templates/modules, you will be in position to generate a basic .NET MAUI project and address multiple usage requirements with just a few clicks:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;MVVM &amp;amp; Dependency Injection:&lt;/strong&gt;&amp;nbsp;A basic setup for MVVM. Ready-to-use application setup.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Authentication and Role-Based Data Access:&lt;/strong&gt;&amp;nbsp;A client-server application based on our free &lt;a href="https://www.devexpress.com/products/net/application_framework/security-web-api-service.xml" target="_blank" rel="noreferrer noopener"&gt;.NET App Security Library &amp;amp; Web API Service&lt;/a&gt;.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;CRUD Operations with Detail/Editing Forms:&lt;/strong&gt;&amp;nbsp;Uses a local SQLite database and a remote Web API service.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Generating Data-Bound Reports:&lt;/strong&gt;&amp;nbsp;Uses DevExpress Reports and our .NET MAUI PDF Viewer control. 
&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Unit Tests:&lt;/strong&gt;&amp;nbsp;A module to help introduce/maintain reliability.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Document Processing:&lt;/strong&gt;&amp;nbsp;Uses the DevExpress&amp;nbsp;&lt;a href="https://www.devexpress.com/products/net/office-file-api/" target="_blank" rel="noreferrer noopener"&gt;Office File API&lt;/a&gt; library.&lt;/p&gt;
    &lt;/li&gt;
&lt;/ul&gt;



&lt;h3&gt;New Page Templates&lt;/h3&gt;

&lt;p&gt;Our page templates will allow you to&amp;nbsp;integrate optimized views into your .NET MAUI project. These page templates offer more than just design and UX solutions; they include control settings, view models, basic logic, and other essential components. We expect to ship the following&amp;nbsp;views in December:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
    &lt;p&gt;CRUD detail/editing forms&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Login forms&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Profile settings views&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Charting views&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Collections with filtering capabilities 
&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Collections with detail data in Bottom Sheet&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Scheduling views&lt;/p&gt;
    &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Predefined XAML Templates&lt;/h3&gt;

&lt;p&gt;In addition to modules and pages, we expect to introduce&amp;nbsp;smaller XAML templates that can be used individually on separate pages. You can browse through all available templates and select those needed for your current requirements. Our predefined XAML templates will be designed based on Material Design 3 guidelines and performance optimization best practices. Here are some of the templates we expect to release:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
    &lt;p&gt;CollectionView item templates.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Popup &amp;amp; BottomSheet-based dialogs.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Various card designs.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Shimmer loading layouts.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Configured form items.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Various gauge types.&lt;/p&gt;
    &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Toolbox&lt;/h3&gt;

&lt;p&gt;v24.2 will include toolbox support. This capability will allow&amp;nbsp;you to quickly add components to a page. When you drop a toolbox item, it will automatically add the appropriate NuGet package and XAML namespace.&lt;/p&gt;

&lt;h2&gt;New Toggle Switch Control&lt;/h2&gt;

&lt;p&gt;We expect to introduce a simple and customizable ToggleSwitch control, based on Material Design 3 guidelines.&lt;/p&gt;


&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:10px;margin:0px 0px 0px 0px;"&gt;
    &lt;img src="https://community.devexpress.com/blogs/mobile/20240715-MAUI-EAP-24-2/24.2-eap-toggle-switch.png" alt=""&gt;
&lt;/div&gt;

&lt;h2&gt;Collection View – Frozen Group Row&lt;/h2&gt;

&lt;p&gt;We expect to add&amp;nbsp;fixed group row support to our .NET MAUI Collection View. Fixed group rows remain visible at the top if at least one child row in the group is visible.&lt;/p&gt;


&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:10px;margin:0px 0px 0px 0px;"&gt;&lt;img src="https://community.devexpress.com/blogs/mobile/20240715-MAUI-EAP-24-2/24.2-eap-cv-freeze-group-header@2x.gif" alt=""&gt;
&lt;/div&gt;

&lt;h2&gt;Collection View &amp;amp; Data Grid– Unlimited Height&lt;/h2&gt;

&lt;p&gt;When displaying a short collection in a scrollable layout, disabling virtualization in the collection may be necessary to ensure it occupies the space used by collection items. This capability allows you to incorporate CollectionView and additional elements into ScrollView with a single vertical scrollbar. We plan to introduce a property that allows you to disable virtualization in CollectionView and expand it based on&amp;nbsp;child items.&lt;/p&gt;

&lt;h2&gt;Filtering UI Elements – Sliders&lt;/h2&gt;

&lt;p&gt;As you know, our .NET MAUI Filtering UI elements allow you to filter data in both our .NET MAUI Collection View and .NET MAUI Data Grid. In v24.2, we will introduce support for sliders within the filtering UI (making it easier for your users to select numeric ranges).&lt;/p&gt;


&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:10px;margin:0px 0px 0px 0px;"&gt;&lt;img src="https://community.devexpress.com/blogs/mobile/20240715-MAUI-EAP-24-2/24.2-eap-cv-sliders-filtering-ui.png" width="50%" alt=""&gt;
&lt;/div&gt;

&lt;h2&gt;Data Grid – Immediate Posting&lt;/h2&gt;

&lt;p&gt;At present, changes to Data Grid cell data are posted to the source only after exiting the active editor. To address this limitation, we will introduce an option to immediately update the data source when a cell is modified by the user.&lt;/p&gt;

&lt;h2&gt;Document Printing&lt;/h2&gt;

&lt;p&gt;We are developing a class to invoke native device printing dialogs. This feature will be accessible via a built-in command in our .NET MAUI PDF Viewer control (or directly in code).&lt;/p&gt;


&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:10px;margin:0px 0px 0px 0px;"&gt;&lt;img src="https://community.devexpress.com/blogs/mobile/20240715-MAUI-EAP-24-2/24.2-eap-pdf-printing.png" width="50%" alt=""&gt;
&lt;/div&gt;

&lt;h2&gt;Text Editors – Hide Max Text Counter&lt;/h2&gt;

&lt;p&gt;We&amp;#39;ve received numerous requests in the DevExpress Support Center to hide the text counter displayed in our .NET MAUI TextEdit and MultilineEdit controls.&amp;nbsp;In our upcoming release (v24.2), we will introduce a property to hide this counter.&lt;/p&gt;


&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:10px;margin:0px 0px 0px 0px;"&gt;&lt;img src="https://community.devexpress.com/blogs/mobile/20240715-MAUI-EAP-24-2/24.2-eap-text-edit-max-count@2x.gif" alt=""&gt;
&lt;/div&gt;

&lt;h2&gt;Integration with MVVM Community Toolkit&lt;/h2&gt;

&lt;p&gt;We&amp;#39;re planning to introduce helper classes built upon the MVVM Community Toolkit library (to help simplify control integration across multiple&amp;nbsp;MVVM usage scenarios).&lt;/p&gt;

&lt;h2&gt;Your Feedback Matters&lt;/h2&gt;
&lt;div data-survey-id="8b601625-cbba-4397-84cc-a8dd400f6983" data-survey-auth-required="false"&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 12 Jul 2024 07:05:00 Z</pubDate>
      <dc:creator>Anthony Sameishchev (DevExpress)</dc:creator>
      <dx:excerpt>In this post, we&amp;#39;ll share our release plans for .NET MAUI in the second half of 2024 (v24.2). If you have any questions about the features/capabilities mentioned in this roadmap, please leave a comment in the survey at the end of this blog.</dx:excerpt>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388152</guid>
      <link>https://community.devexpress.com/Blogs/mobile/archive/2024/05/24/net-maui-collection-view-switch-between-different-item-representations.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.net+maui">.net maui</category>
      <category domain="https://community.devexpress.com/Tags/Android">Android</category>
      <category domain="https://community.devexpress.com/Tags/iOS">iOS</category>
      <category domain="https://community.devexpress.com/Tags/maui">maui</category>
      <category domain="https://community.devexpress.com/Tags/mobile">mobile</category>
      <category domain="https://community.devexpress.com/Tags/v23.2">v23.2</category>
      <title> .NET MAUI Collection View — Switch Between Different Item Representations</title>
      <description>&lt;p&gt;How many different ways can you present information using the CollectionView? More importantly, which presentation option should you choose&amp;nbsp;for the best possible user experience? Here is our recommendation: Consider offering  users multiple options and let them choose based on requirements/preferences.&lt;/p&gt;

&lt;p&gt;As you might have guessed by now, the DevExpress .NET MAUI&amp;nbsp;CollectionView allows you to  switch between multiple data presentation modes: single/multiple columns or simple/detailed item template. In this blog post, we will review both options&amp;nbsp;in detail.&lt;/p&gt;

&lt;h2&gt;Multi-Span Layout&lt;/h2&gt;

&lt;p&gt;In one of our minor releases (v23.2.4), we’ve extended our DXCollectionView with a new &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSpanCount"&gt;DXCollectionView.ItemSpanCount&lt;/a&gt; property so you can easily display CollectionView items across a multi-column list. This property allows you to set the number of&amp;nbsp;columns (&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.Orientation"&gt;Orientation&lt;/a&gt; is &lt;code&gt;Vertical&lt;/code&gt;) or rows (&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.Orientation"&gt;Orientation&lt;/a&gt; is &lt;code&gt;Horizontal&lt;/code&gt;) the DXCollectionView must display on-screen.&lt;/p&gt;

&lt;p&gt;
&lt;img src="https://community.devexpress.com/blogs/mobile/20240514-cv-item-representations/collectionview-singlecolumn-vs-multiplecolumn.png" class="small" width="50%" alt="DevExpress CollectionView for .NET MAUI - Multi-span layout"&gt;
&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-xml"&gt;
&amp;lt;dxcv:DXCollectionView 
        x:Name=&amp;quot;collectionView&amp;quot;
        ItemSpanCount=&amp;quot;{Binding ColumnsCount}&amp;quot;&amp;gt;
    &amp;lt;!--...--&amp;gt;
&amp;lt;/dxcv:DXCollectionView&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The complete source code for our demo app is available on GitHub: &lt;a href="https://github.com/DevExpress-Examples/maui-collection-view/tree/23.2.4%2B/CS/CollectionViewFilteringUI#readme"&gt;Collection View - Filtering UI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To design a more flexible user interface, you can calculate the number of collection view spans (columns or rows) based on  device type (phone or tablet) and screen orientation (landscape or portrait). Obviously, a tablet screen in landscape mode can fit more data items - improving readability when compared to a mobile phone screen.&lt;/p&gt;

&lt;p&gt;With this fact in mind, let’s add selection logic for the&amp;nbsp;&lt;code&gt;ItemSpanCount&lt;/code&gt; property value based on device parameters. To do so, we’ll use our multi-functional &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Core.ON"&gt;ON&lt;/a&gt; class and its &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Core.ON.Idiom--1(--0---0)?v=24.1"&gt;ON.Idiom&lt;/a&gt;, &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Core.ON.Orientation--1(--0---0)?v=24.1"&gt;ON.Orientation&lt;/a&gt; and &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Core.ON.OrientationChanged--1(--0-System.Action---0-)?v=24.1"&gt;ON.OrientationChanged&lt;/a&gt; methods. The following code snippet determines the number of Collection View columns to display.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;
public MainPage() {
    //...
    ON.OrientationChanged(this, OnOrientationChanged);
    OnOrientationChanged(this);
}
void OnOrientationChanged(ContentPage view) {
    UpdateColumnsCount();
}
void UpdateColumnsCount() {
    ViewModel.ColumnsCount = ON.Idiom&amp;lt;int&amp;gt;(ON.Orientation&amp;lt;int&amp;gt;(1, 2), ON.Orientation&amp;lt;int&amp;gt;(2, Height &amp;lt; 600 ? 2 : 4));
}
&lt;/code&gt;&lt;/pre&gt;


&lt;h2&gt;Simplified and Detailed Item Template&lt;/h2&gt;

&lt;p&gt;Additionally, we can vary visual representation of items when using single-column and multi-column modes. This approach can address a diverse set of user preferences and usage scenarios.&lt;/p&gt;

&lt;p&gt;The amount of information displayed&amp;nbsp;for a single item may also depend on user preferences. For example, users with impaired vision will typically prefer larger items in a single column. In this instance, you can display&amp;nbsp;less detail, but improve overall&amp;nbsp;readability.&lt;/p&gt;

&lt;p&gt;You may also want to display&amp;nbsp;more details when a user filters them against a criteria. For example, if you need to filter the list by the number of orders, you may want to switch to detailed mode to view numbers on-screen.&lt;/p&gt;

&lt;p&gt;In our example, we select a simple item template in multi-column mode and a detailed item template in single mode. To deliver this capability, we implemented the &lt;code&gt;ColumnsCountToTemplateConverter&lt;/code&gt; that conditionally selects a&amp;nbsp;template to apply to the &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemTemplate?v=24.1"&gt;ItemTemplate&lt;/a&gt; property (based&amp;nbsp;on the number of DXCollectionView layout columns).&lt;/p&gt;

&lt;p&gt;
&lt;img src="https://community.devexpress.com/blogs/mobile/20240514-cv-item-representations/collection-view-itemtemplate.png" class="small" width="50%" alt="DevExpress CollectionView for .NET MAUI - Item template"&gt;
&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-xml"&gt;
&amp;lt;ContentPage.Resources&amp;gt;
    &amp;lt;utils:ColumnsCountToTemplateConverter x:Key=&amp;quot;cardTemplateConverter&amp;quot; SmallCardTemplate=&amp;quot;{StaticResource smallHouseCardTemplate}&amp;quot; CardTemplate=&amp;quot;{StaticResource houseCardTemplate}&amp;quot;/&amp;gt;
&amp;lt;/ContentPage.Resources&amp;gt;
    &amp;lt;!--...--&amp;gt;
    &amp;lt;dxcv:DXCollectionView 
        x:Name=&amp;quot;collectionView&amp;quot; 
        ItemsSource=&amp;quot;{Binding ItemsSource}&amp;quot; 
        ItemTemplate=&amp;quot;{Binding ColumnsCount, Converter={StaticResource cardTemplateConverter}}&amp;quot; &amp;gt;
    &amp;lt;/dxcv:DXCollectionView&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;
public class ColumnsCountToTemplateConverter : IValueConverter {
    public DataTemplate SmallCardTemplate { get; set; }
    public DataTemplate CardTemplate { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        return ON.Idiom&amp;lt;DataTemplate&amp;gt;((int)value &amp;gt; 1 ? SmallCardTemplate : CardTemplate, CardTemplate);
    }

    //...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Summary&lt;/h2&gt;&lt;p&gt;

By providing users with flexible item presentation options (and by using our flexible .NET MAUI CollectionView component), you can address a variety of business requirements/use cases. 
&lt;/p&gt;&lt;p&gt;To learn more about our .NET MAUI product line, refer to the following blog posts:&amp;nbsp;&lt;/p&gt;&lt;ul&gt;
    &lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2024/04/01/How-to-Profile-NET-MAUI-Applications-and-Isolate-Performance-Related-Issues.aspx"&gt;How to Profile .NET MAUI Applications and Isolate Performance-Related Issues&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2024/01/08/net-maui-bottom-sheet-3-ways-to-optimize-mobile-screen-space.aspx"&gt;.NET MAUI Bottom Sheet — 3 Ways to Optimize Mobile Screen Space&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2023/10/18/incorporate-crud-operations-into-your-app-with-devexpress-net-maui-collectionview.aspx"&gt;.NET MAUI — Incorporate CRUD Operations in Your Mobile App with DevExpress CollectionView&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2023/10/12/net-maui-mobile-collection-filtering-best-practices.aspx"&gt;.NET MAUI Mobile — Collection Filtering Best Practices&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2023/11/02/3-combobox-dropdown-alternatives-to-implement-user-friendly-item-selection-in-a-mobile-app.aspx"&gt;.NET MAUI — 3 ComboBox Dropdown Alternatives for User-Friendly Item Selection within a Mobile App&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Fri, 24 May 2024 02:13:00 Z</pubDate>
      <dc:creator>Kseniya Kuzmina (DevExpress)</dc:creator>
      <dx:excerpt>How many different ways can you present information using the CollectionView? More importantly, which presentation option should you choose for the best possible user experience? Here is our recommendation: Consider offering users multiple options and let them choose based on requirements/preferences.</dx:excerpt>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388153</guid>
      <link>https://community.devexpress.com/Blogs/mobile/archive/2024/05/22/how-to-implement-material-design-3-in-a-net-maui-application.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.net+maui">.net maui</category>
      <category domain="https://community.devexpress.com/Tags/2023">2023</category>
      <category domain="https://community.devexpress.com/Tags/Android">Android</category>
      <category domain="https://community.devexpress.com/Tags/iOS">iOS</category>
      <category domain="https://community.devexpress.com/Tags/maui">maui</category>
      <category domain="https://community.devexpress.com/Tags/mobile">mobile</category>
      <category domain="https://community.devexpress.com/Tags/v23.2">v23.2</category>
      <title>How to Implement Material Design 3 in a .NET MAUI Application</title>
      <description>&lt;p&gt;&lt;a href="https://m3.material.io/"&gt;Material Design&lt;/a&gt; is a cross-platform system of guidelines developed by Google. Inspired by the textures of the physical world, it helps you craft visually captivating interfaces with balanced colors and enhanced usability (the objective is to focus attention on essential UI elements).

    The DevExpress .NET MAUI Suite includes&amp;nbsp;10 built-in Material Design 3 color themes -&amp;nbsp;available in both dark and light variants. With the help of the ThemeColor markup extension and project templates, you can easily support Material Design 3 themes in applications using DevExpress or standard .NET MAUI controls.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;img src="https://community.devexpress.com/blogs/mobile/20240517-material-design/material-design-overview.png" alt="Material Design 3 - Overview"&gt;&lt;/p&gt;

&lt;h2 id="access-the-material-design-3-palette"&gt;Access the Material Design 3 Palette&lt;/h2&gt;

&lt;p&gt;Material Design 3 Palette is generated based on a given seed color. From this color, the Material Design 3 algorithm creates six tonal palettes. To support dark and light application appearance, the algorithm takes colors from tonal palettes and creates color schemes. Material Design 3 ensures color scheme&amp;nbsp;colors have sufficient contrast and a consistent appearance. To use Material Design 3 colors in your application, simply bind controls directly to a color scheme&amp;#39;s colors. Refer to the &lt;a href="https://docs.devexpress.com/MAUI/404636/common-concepts/themes#color-theme-anatomy"&gt;Color Theme Anatomy&lt;/a&gt; section for more information.&lt;/p&gt;

&lt;p&gt;To simplify bindings, we ship a &lt;a href="https://docs.devexpress.com/MAUI/404636/common-concepts/themes#apply-color-themes"&gt;ThemeManager&lt;/a&gt; class. This member allows you to generate a new theme based on a seed color and apply it to the application. This capability will be of value for those who wish to style applications based on brand colors.&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp" data-line-numbers="true"&gt;using DevExpress.Maui;
using DevExpress.Maui.Core;
using Microsoft.Maui.Graphics;

// ...
public static class MauiProgram {
    public static MauiApp CreateMauiApp() {
        ThemeManager.UseAndroidSystemColor = false;
        ThemeManager.Theme = new Theme(Color.FromArgb(&amp;quot;FF6200EE&amp;quot;));
        var builder = MauiApp.CreateBuilder();
        builder
            .UseDevExpress()
            // ...
            .UseMauiApp&amp;lt;App&amp;gt;();
        return builder.Build();
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can also use the APIs mentioned above to apply a predefined theme to your application:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp" data-line-numbers="true"&gt;using DevExpress.Maui;
using DevExpress.Maui.Core;

// ...
public static class MauiProgram {
    public static MauiApp CreateMauiApp() {
        ThemeManager.UseAndroidSystemColor = false;
        ThemeManager.Theme = new Theme(ThemeSeedColor.TealGreen);
        var builder = MauiApp.CreateBuilder();
        builder
            .UseDevExpress() 
            // ...
            .UseMauiApp&amp;lt;App&amp;gt;();
        return builder.Build();
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When you need to use a color scheme&amp;#39;s color, you can use the ThemeColor markup extension to pick a color by its token name.&lt;/p&gt;

&lt;p&gt;To maintain application consistency&amp;nbsp;with the&amp;nbsp;appearance of a device, we also added the &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Core.ThemeManager.UseAndroidSystemColor"&gt;ThemeManager.UseAndroidSystemColor&lt;/a&gt; property. It takes the primary color of your Android device as a seed color, generates a new theme based on it, and applies the theme to the application.&lt;/p&gt;

&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:4%;margin:0px 0px 0px 0px;"&gt;
&lt;img src="https://community.devexpress.com/blogs/mobile/20240517-material-design/android-system-color.png" alt="DevExpress Material Design 3 Themes" width="40%"&gt;
&lt;/div&gt;

&lt;p&gt;Additionally, you can set a custom navigation bar&amp;#39;s background and foreground colors (available on Android OS), status bar background color (available on Android OS), and status bar foreground color (for both Android OS and iOS).&lt;/p&gt;&lt;pre&gt;&lt;code class="language-csharp"&gt;ThemeManager.Theme = new Theme(ThemeSeedColor.DarkGreen);
ThemeManager.AndroidNavigationBarForeground = AppTheme.Light;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Refer to the following topic for additional guidance:&amp;nbsp;&amp;nbsp;&lt;a href="https://docs.devexpress.com/MAUI/404636/common-concepts/themes#apply-system-colors-to-system-bars"&gt;Apply System Colors to System Bars&lt;/a&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;
    You can also visit the &lt;a href="https://github.com/DevExpress-Examples/maui-demo-app/"&gt;DevExpress .NET MAUI Demo Center&lt;/a&gt; GitHub repository to view our theme engine in action.
&lt;/p&gt;


&lt;h2 id="use-predefined-material-design-styles"&gt;Use Predefined Material Design Styles&lt;/h2&gt;
&lt;p&gt;The default appearances of our .NET MAUI Controls meet Material Design 3 guideline requirements. Like&amp;nbsp;Material Design 3, our controls support multiple types: Accent, Filled, Outlined, and Text.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://community.devexpress.com/blogs/mobile/20240517-material-design/button-types@2x.png" alt=""&gt;&lt;/p&gt;

&lt;p&gt;When it comes to application&amp;nbsp;appearance, design consistency of utmost importance. If you use both standard controls and DevExpress .NET MAUI Controls in a single solution, you can apply our color themes to standard controls to introduce consistency across your entire mobile project.&lt;/p&gt;
&lt;p&gt;If you create a new application, you do not need to worry about extra code because we added styles for standard controls in our project templates. If you already have an application, you simply need to use our &lt;a href="https://docs.devexpress.com/MAUI/404636/common-concepts/themes?v=24.1#apply-color-theme-colors-to-a-standard-control"&gt;ThemeColor markup extension&lt;/a&gt; to bind standard controls to DevExpress .NET MAUI Color Themes.&lt;/p&gt;&lt;pre&gt;&lt;code class="language-xml" data-line-numbers="true"&gt;
&amp;lt;VerticalStackLayout BackgroundColor=&amp;quot;{dx:ThemeTertiaryColor Light=10, Dark=100}&amp;quot;&amp;gt;
    &amp;lt;Label Text=&amp;quot;Faux Available&amp;quot; TextColor=&amp;quot;{dx:ThemeColor OnSurface}&amp;quot;/&amp;gt;
    &amp;lt;Button Text=&amp;quot;Open File&amp;quot; BackgroundColor=&amp;quot;{dx:ThemePrimaryColor Light=40, Dark=80}&amp;quot;/&amp;gt;
&amp;lt;/VerticalStackLayout&amp;gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Refer to the following topic for more information in this regard:&amp;nbsp;&lt;a href="https://docs.devexpress.com/MAUI/404636/common-concepts/themes#apply-color-theme-colors-to-a-standard-control"&gt;Apply Color Theme to a Standard Control&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;span&gt;To review sample code used to theme&amp;nbsp;standard .NET MAUI controls:&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;a href="https://github.com/DevExpress-Examples/maui-theme-standard-controls"&gt;Apply Themes to Standard Controls&lt;/a&gt;&amp;nbsp;&lt;/p&gt;


&lt;h2 id="conclusion"&gt;Summary&lt;/h2&gt;
&lt;p&gt;Material Design 3 principles help you deliver mobile solutions with a consistent, modern appearance. While Material Design 3 includes many rules and uses sophisticated algorithms for color calculation, our components and predefined project templates have been designed to style your app with relative ease.&lt;/p&gt;</description>
      <pubDate>Wed, 22 May 2024 05:25:00 Z</pubDate>
      <dc:creator>Anthony Sameishchev (DevExpress)</dc:creator>
      <dx:excerpt>Material Design is a cross-platform system of guidelines developed by Google. Inspired by the textures of the physical world, it helps you craft visually captivating interfaces with balanced colors and enhanced usability (the objective is to focus attention on essential UI elements). The DevExpress .NET MAUI Suite includes 10 built-in Material Design 3 color themes - available in both dark and light variants.</dx:excerpt>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388151</guid>
      <link>https://community.devexpress.com/Blogs/mobile/archive/2024/05/02/choosing-a-framework-and-app-architecture-for-desktop-and-mobile-cross-platform-apps.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.net">.net</category>
      <category domain="https://community.devexpress.com/Tags/.net+maui">.net maui</category>
      <category domain="https://community.devexpress.com/Tags/Android">Android</category>
      <category domain="https://community.devexpress.com/Tags/featured">featured</category>
      <category domain="https://community.devexpress.com/Tags/iOS">iOS</category>
      <category domain="https://community.devexpress.com/Tags/maui">maui</category>
      <category domain="https://community.devexpress.com/Tags/mobile">mobile</category>
      <category domain="https://community.devexpress.com/Tags/webapi">webapi</category>
      <category domain="https://community.devexpress.com/Tags/winforms">winforms</category>
      <category domain="https://community.devexpress.com/Tags/wpf">wpf</category>
      <title>Choosing a Framework/App Architecture for Desktop &amp; Mobile Cross-Platform Apps</title>
      <description>&lt;p&gt;“&lt;em&gt;Write once, run anywhere&lt;/em&gt;&amp;quot; – this slogan&amp;nbsp;helped Java achieve widespread popularity&amp;nbsp;in the mid-1990s. Since then, many cross-platform frameworks have been introduced, such as Ionic, Flutter, and of course .NET MAUI. These frameworks allow developers to use the same code regardless of the&amp;nbsp;underlying operating system/device type. While using a single UI framework may save  time/resources, the effectiveness and efficiency of this development strategy&amp;nbsp;depends entirely on&amp;nbsp;app complexity and UX requirements. &lt;/p&gt;
&lt;p&gt;An alternative technique to a&amp;nbsp;cross-platform app is to share business logic and services but use different UI frameworks based on  device type (desktop/mobile). With this strategy, you will share less UI code, but use the inherent benefits/advantages of each platform to craft high-quality interfaces (and of course deliver the best possible user experience across platforms/devices).&lt;/p&gt;
&lt;p style="background-color:white;"&gt;&lt;video autoplay="" loop="" muted="" style="width:780px;height:446px;"&gt;
  &lt;source src="https://community.devexpress.com/blogs/mobile/20240426-desktop-mobile-shared-code/CrmWpfMauiApp.mp4" type="video/mp4"&gt;
  Your browser does not support the video tag.
&lt;/video&gt;&lt;/p&gt;
&lt;a href="https://github.com/DevExpress-Examples/wpf-winforms-maui-shared-codebase" class="Button Gray"&gt;Download Example&lt;/a&gt; 
&lt;h2 id="single-ui-project-advantages-and-challenges"&gt;Single UI Project: Advantages and Challenges&lt;/h2&gt;
&lt;p&gt;A fully cross-platform interface can help dev&amp;nbsp;teams reduce development costs and time-to-market. For instance, a single page created using Blazor can be used in web, desktop and mobile apps via Blazor Hybrid. And this is not just a WebView wrapper for web components: it allows you to run code in the .NET environment while accessing device capabilities. This strategy can improve team productivity, because you can share code and  expertise.  &lt;/p&gt;
&lt;div class="Note"&gt;The following article will help you create your first Blazor Hybrid app: &lt;a href="https://docs.devexpress.com/Blazor/404118/get-started/blazor-hybrid/blazor-hybrid" target="_blank"&gt;Get Started - Blazor Hybrid&lt;/a&gt;.&lt;/div&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Another rapidly evolving cross-platform framework is .NET MAUI. It was designed to support different device types (desktop, mobile, tablet). The framework includes useful features designed&amp;nbsp;to share code between different targets: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Project Structure: Unlike Xamarin, .NET MAUI incorporates all cross-platform code in a single project. &lt;/li&gt;
&lt;li&gt;Device-specific customization:&amp;nbsp;Adaptive layout XAML extensions allow you to update control properties based on  device and operating system type. &lt;/li&gt;
&lt;li&gt;Native UI elements: Under the hood,  .NET components are converted into native OS-specific elements, ensuring&amp;nbsp;a device-specific user experience. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These core features can help you create apps with a single codebase targeted to different devices. You can find a sample app demonstrating .NET MAUI&amp;#39;s cross-platform capabilities in the following repository (created by the Microsoft team): &lt;a href="https://github.com/davidortinau/WeatherTwentyOne" target="_blank"&gt;Weather &amp;#39;21&lt;/a&gt;.  &lt;/p&gt;
&lt;p&gt;Here is an example of how to specify different layouts for phone and desktop devices (one column for a phone and two columns for a desktop):  &lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;Grid ColumnDefinitions=&amp;quot;{OnIdiom Phone=&amp;#39;*&amp;#39;, Desktop=&amp;#39;*,500&amp;#39;}&amp;quot; ... &amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This technique works great for relatively simple apps. However, business applications often require more sophisticated device-specific alterations. For example, the desktop client may include complex views with a Ribbon and Docking. These controls are typically replaced by other elements on mobile devices. &lt;/p&gt;
&lt;p&gt;Moreover, the entire user flow may differ significantly on a phone. For instance, in-place cell editing is common for desktop apps, however for mobile devices you may prefer to  display detail and editing screens separately. You can find this pattern in many applications on your phone (such as Contacts).  &lt;/p&gt;
&lt;p&gt;The following images illustrate a few examples where it may be challenging to create a single UI code base: &lt;/p&gt;
&lt;div style="margin-left:auto;margin-right:auto;display:flex;flex-wrap:wrap;justify-content:space-around;"&gt;
    &lt;img src="https://community.devexpress.com/blogs/mobile/20240426-desktop-mobile-shared-code/master-detail@2x.png" alt="BottomSheet ComboBox" style="max-width:370px;max-height:280px;object-fit:contain;margin-bottom:20px;"&gt; 
    &lt;img src="https://community.devexpress.com/blogs/mobile/20240426-desktop-mobile-shared-code/filteringUI@2x.png" alt="BottomSheet FormItems" style="max-width:370px;max-height:280px;object-fit:contain;margin-bottom:20px;"&gt;
    &lt;img src="https://community.devexpress.com/blogs/mobile/20240426-desktop-mobile-shared-code/Cell-Editing@2x.png" alt="BottomSheet FormItems" style="max-width:370px;max-height:280px;object-fit:contain;margin-bottom:20px;"&gt;
    &lt;img src="https://community.devexpress.com/blogs/mobile/20240426-desktop-mobile-shared-code/docking@2x.png" alt="BottomSheet FormItems" style="max-width:370px;max-height:280px;object-fit:contain;margin-bottom:20px;"&gt;
&lt;/div&gt;
&lt;p&gt;When there&amp;#39;s a significant difference&amp;nbsp;between  desired desktop and mobile interfaces, creating numerous device-specific triggers may quickly complicate&amp;nbsp;your code (making it hard to develop and maintain).  &lt;/p&gt;
&lt;h2 id="apps-with-device-specific-ui-frameworks"&gt;Apps with Device-Specific UI Frameworks&lt;/h2&gt;
&lt;p&gt;Using a single UI platform provides more opportunities for code sharing, however it&amp;#39;s challenging to leverage these benefits when working on applications with a complex interface. If you are developing such an app, you may want to use&amp;nbsp;separate UI frameworks for different client types and reuse non-visual code. This allows you to take  advantage&amp;nbsp;of each platform and still share quite a bit of code. &lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240426-desktop-mobile-shared-code/SharedCodeArchitecture.jpg" alt=""&gt;
&lt;p&gt;In the illustration above,  client apps are implemented using different UI frameworks, while&amp;nbsp;both clients use common services, business logic and server-side modules.  Based on your preferences, you can either implement all server logic as a single service or create a microservices infrastructure.  &lt;/p&gt;
&lt;p&gt;On the client side, you can select the platforms best suited for your application: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt; WPF and WinForms (both very mature platforms) offer you a variety&amp;nbsp;of important features and capabilities for rich desktop user experiences. &lt;/li&gt;
&lt;li&gt;Lightweight .NET MAUI will allow you to create an application with a&amp;nbsp;mobile centric UX for Android and iOS.  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since WPF, WinForms and MAUI are .NET - based, you can easily reuse client-side services, helpers and model classes. The key to more code sharing is a loosely coupled architecture when modules can be isolated from each other. The MVVM design pattern will help you decouple your views from view models and easily introduce external dependencies using &lt;a href="https://community.devexpress.com/blogs/wpf/archive/2022/02/07/dependency-injection-in-a-wpf-mvvm-application.aspx" target="_blank"&gt;Dependency Injection&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;If you pursue this strategy, your project structure may look as follows: &lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240426-desktop-mobile-shared-code/ProjectStructure.png" alt="" class="small" style="width:487px;height:226px;"&gt;
&lt;ul&gt;
&lt;li&gt;Client.Shared - client-side services, common helpers. &lt;/li&gt;
&lt;li&gt;DataModel - a model for database objects. &lt;/li&gt;
&lt;li&gt;DesktopClient - WPF/WinForms application &lt;/li&gt;
&lt;li&gt;MobileClient - .NET MAUI application &lt;/li&gt;
&lt;li&gt;WebApiService - a web service that incorporates business logic and handles access to a database. Note: You can utilize our free &lt;a href="https://www.devexpress.com/products/net/application_framework/security-web-api-service.xml" target="_blank"&gt;Web API Service&lt;/a&gt; to implement  server-side security and role-based data access. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&amp;#39;d like to explore the potential of this&amp;nbsp;strategy, download our sample application at GitHub:&amp;nbsp;&lt;a href="https://github.com/DevExpress-Examples/wpf-winforms-maui-shared-codebase" target="_blank"&gt;WPF &amp;amp; .NET MAUI - Share Code Between Desktop and Mobile Projects&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="Note"&gt;Our &lt;a href="https://www.devexpress.com/products/net/application_framework/" target="_blank"&gt;Cross-Platform .NET App UI (XAF)&lt;/a&gt; is based on a similar idea and has demonstrated its effectiveness for over 15 years. Data processing, security, business logic, and other shared modules are designed as view-agnostic blocks. When introducing a new visual client, you can easily reuse most of your code.&lt;/div&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Below, you&amp;#39;ll find insights from Paul Usher (Business Solutions Architect and DevExpress Evangelist, experienced in Xamarin and .NET MAUI, as well as native iOS &amp;amp; Android): &lt;/p&gt;
&lt;blockquote&gt;&lt;img style="width:160px;height:160px;float:left;margin-right:35px;" src="https://community.devexpress.com/blogs/mobile/20240120-MobileOnly-Controls/Paul-testimonials.png" alt="Managing Director" width="20%"&gt;
    There is so much more freedom in separating mobile platforms from desktop. Given your data layer and business logic should be their own seperate projects it makes sense to concentrate development efforts on iOS and Android delivering specific goals for mobile use. The Desktop interface can then be designed specifically to optimise the features required. Typically a mobile version of an application contains less functionality but geared towards more practical &amp;quot;in your hand&amp;quot; usage, whereas the desktop version provides a much deeper, richer user experience utilizing more screen realestate, multiple complex components on screen at the same time.
&lt;/blockquote&gt;
&lt;h2 id="conclusion"&gt;&lt;br&gt;&lt;/h2&gt;&lt;h2 id="conclusion"&gt;Summary&lt;/h2&gt;
&lt;p&gt;Choosing the best possible UI framework for a given platform is crucial as it shapes&amp;nbsp;the development process, user experience, and ultimately, the success of the project. A unified cross-platform UI can be an effective solution for simpler applications, Minimum Viable Products (MVPs), or when user experience excellence for a secondary device isn’t the primary concern. &lt;/p&gt;&lt;p&gt;For more complex applications, the potential for sharing UI code can be limited due to the significant differences in user flow for desktop and mobile devices. By separating visual clients and leveraging advantages of each UI platform you can develop high-impact apps&amp;nbsp;that cater to user needs with laser-like precision. A loosely coupled architecture not only allows for extensive code reuse but also ensures that the code remains clean, maintainable, and testable.&lt;/p&gt;&lt;h2&gt;Additional References on Application Architectures&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/news/archive/2024/02/09/modern-desktop-apps-and-their-complex-architectures.aspx" target="_blank" rel="nofollow noreferrer"&gt;Intro — Modern Desktop Apps And Their Complex Architectures&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="background-color:#ffff99;"&gt;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2024/05/02/choosing-a-framework-and-app-architecture-for-desktop-and-mobile-cross-platform-apps.aspx" target="_blank"&gt;Choosing a Framework/App Architecture for Desktop &amp;amp; Mobile Cross-Platform Apps&lt;/a&gt;&amp;nbsp;/&amp;nbsp;&lt;a href="https://github.com/DevExpress-Examples/wpf-winforms-maui-shared-codebase" target="_blank"&gt;GitHub sample&lt;/a&gt;&amp;nbsp;&lt;strong&gt;(this post)&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/news/archive/2024/08/30/connect-a-winforms-data-grid-to-a-net-core-service.aspx" target="_blank"&gt;Connect a .NET Desktop Client (WinForms&amp;nbsp;Data Grid)&amp;nbsp;to a Custom ASP.NET Core Service (&lt;/a&gt;&lt;strong&gt;&lt;a href="https://community.devexpress.com/blogs/news/archive/2024/08/30/connect-a-winforms-data-grid-to-a-net-core-service.aspx" target="_blank"&gt;EF Core with pure Web&amp;nbsp;API&lt;/a&gt;&lt;/strong&gt;&lt;a href="https://community.devexpress.com/blogs/news/archive/2024/08/30/connect-a-winforms-data-grid-to-a-net-core-service.aspx" target="_blank"&gt;)&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/news/archive/2024/08/30/connect-a-winforms-data-grid-to-a-net-core-service.aspx" target="_blank"&gt;Part 1 — Architecture and Data Binding&lt;/a&gt;&amp;nbsp; /&amp;nbsp;&lt;a href="https://github.com/DevExpress-Examples/connect-winforms-grid-to-dotnetcore-service" target="_blank"&gt;GitHub&amp;nbsp;sample&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/news/archive/2024/09/23/connect-a-winforms-data-grid-to-an-arbitrary-asp-net-core-webapi-service-powered-by-ef-core-add-editing-features.aspx" target="_blank"&gt;Part 2 — Add Editing Features&lt;/a&gt;&amp;nbsp;/&amp;nbsp;&lt;a href="https://github.com/DevExpress-Examples/connect-winforms-grid-to-dotnetcore-service-enable-editing" target="_blank" rel="nofollow noreferrer"&gt;GitHub sample&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/news/archive/2024/10/08/connect-a-winforms-data-grid-to-an-arbitrary-asp-net-core-webapi-service-powered-by-ef-core-authenticate-users-and-protect-data.aspx" target="_blank"&gt;Part&amp;nbsp;3&amp;nbsp;— Authenticate Users and Protect Data&lt;/a&gt;&amp;nbsp;/&amp;nbsp;&lt;a href="https://github.com/DevExpress-Examples/connect-winforms-grid-to-dotnetcore-service-enable-pbac" target="_blank"&gt;GitHub sample&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;a href="https://community.devexpress.com/blogs/news/archive/2024/12/18/connect-a-winforms-data-grid-to-an-arbitrary-asp-net-core-webapi-service-powered-by-ef-core-authorization-code-flow.aspx" target="_blank"&gt;Part 4&amp;nbsp;— Authorization Code Flow with&amp;nbsp;Keycloak&lt;/a&gt;&amp;nbsp;/&amp;nbsp;&lt;a href="https://github.com/DevExpress-Examples/connect-winforms-grid-to-dotnetcore-service-enable-auth-code-flow" target="_blank"&gt;GitHub sample&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/winforms/archive/2024/07/18/winforms-connect-a-net-desktop-client-to-a-secure-backend-with-the-devexpress-web-api-service-ef-core-with-odata.aspx" target="_blank"&gt;Connect a .NET Desktop Client (WinForms&amp;nbsp;Data Grid)&amp;nbsp;to a Secure Backend Web API Service (&lt;strong&gt;EF Core&amp;nbsp;&lt;/strong&gt;&lt;strong&gt;with&lt;/strong&gt;&lt;strong&gt;&amp;nbsp;OData&lt;/strong&gt;)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/winforms/archive/2024/09/18/winforms-connect-net-desktop-client-to-secure-backend-with-middle-tire-server-ef-core.aspx" target="_blank"&gt;Connect a .NET Desktop Client (WinForms Data Grid) to a&amp;nbsp;Middle Tier Security Server (&lt;strong&gt;EF Core&amp;nbsp;&lt;/strong&gt;&lt;strong&gt;with&amp;nbsp;WebSockets&lt;/strong&gt;)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;TBD&amp;nbsp;—&amp;nbsp;Azure Databases with Data API Builder&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;TBD&amp;nbsp;—&amp;nbsp;GraphQL APIs&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;We also have related blog series, which may be of interest for you as well:&amp;nbsp;&lt;a href="https://community.devexpress.com/blogs/news/archive/2023/04/11/consume-the-devexpress-backend-web-api-from-javascript-with-svelte-part-1.aspx" target="_blank"&gt;JavaScript — Consume the DevExpress Backend Web API with Svelte&lt;/a&gt;&amp;nbsp;(7 parts from data editing to validation,&amp;nbsp;localization, reporting).&lt;/p&gt;</description>
      <pubDate>Thu, 02 May 2024 01:20:00 Z</pubDate>
      <dc:creator>Alexander Russkov (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388143</guid>
      <link>https://community.devexpress.com/Blogs/mobile/archive/2024/04/23/net-maui-html-edit-control.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.net+maui">.net maui</category>
      <category domain="https://community.devexpress.com/Tags/Android">Android</category>
      <category domain="https://community.devexpress.com/Tags/htmledit">htmledit</category>
      <category domain="https://community.devexpress.com/Tags/iOS">iOS</category>
      <category domain="https://community.devexpress.com/Tags/maui">maui</category>
      <category domain="https://community.devexpress.com/Tags/mobile">mobile</category>
      <category domain="https://community.devexpress.com/Tags/v23.2">v23.2</category>
      <category domain="https://community.devexpress.com/Tags/videos">videos</category>
      <title>.NET MAUI: Edit HTML Content with the DevExpress .NET MAUI HTML Edit Control</title>
      <description>&lt;p&gt;In the late 80s, physicist Tim Berners-Lee created the first prototype of HTML - a unified format designed to share documents between researchers.&lt;/p&gt;

&lt;p&gt;Since then, HTML adoption has&amp;nbsp;grown exponentially, and is now used in&amp;nbsp;browsers, email clients, and CMS systems. Needless to say,  rich content stored in HTML format is used across&amp;nbsp;the web and within  applications able to&amp;nbsp;render HTML. Thanks to its versatility, HTML is now ubiquitous.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If HTML editing&amp;nbsp;is important to your mobile development strategy, the DevExpress&amp;nbsp;.NET MAUI HTML Edit Control can help you&amp;nbsp;incorporate HTML editing within your mobile solution and address a variety of usage&amp;nbsp;scenarios, including:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;introduce rich text notes&lt;/li&gt;
	&lt;li&gt;write comments/messages&lt;/li&gt;
	&lt;li&gt;compose email messages&lt;/li&gt;
    &lt;li&gt;create content for a CMS system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this blog post, I&amp;#39;ll use the DevExpress .NET MAUI HTML Edit to display and edit descriptions of homes&amp;nbsp;within&amp;nbsp;a simple mobile application (using a CRUD editing form).&lt;/p&gt;

&lt;img src="https://community.devexpress.com/blogs/mobile/20240422-HTMLEdit/property-details-animation@2x.gif" alt="HTML Edit Overview Animation"&gt;

&lt;p&gt;The application showcased in this post is available on GitHub: &lt;a href="https://github.com/DevExpress-Examples/maui-html-edit/tree/23.2.3%2B/CS/PropertyDescription"&gt;Edit HTML in DataGridView CRUD Views&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;
    You can also watch a tutorial video on YouTube if you expect to integrate our .NET MAUI&amp;nbsp;HTML Edit Control in your next .NET MAUI project.&amp;nbsp;
&lt;/p&gt;

&lt;iframe width="560" height="321" src="https://www.youtube-nocookie.com/embed/gne2Olr_uiw" allowfullscreen="" style="width:560px;" referrerpolicy="strict-origin-when-cross-origin"&gt;&lt;/iframe&gt;


&lt;div class="Note"&gt;
    &lt;p&gt;The primary goal of our HTML Edit Control is to create/edit rich text content to be displayed in other components/applications. It doesn&amp;#39;t support all HTML tags, such as interactive buttons, borders, etc.&lt;/p&gt;
    &lt;p&gt;
        To use the&amp;nbsp;DevExpress .NET MAUI HTML Edit control in a project,&amp;nbsp;you must purchase a DevExpress&amp;nbsp;Universal Subscription. If you are new to our .NET MAUI product line and are considering it for an upcoming project, you can start a 30-day trial using  NuGet as described in &lt;a href="https://docs.devexpress.com/GeneralInformation/116042/nuget/obtain-your-nuget-feed-credentials#start-a-30-day-trial-period"&gt;this help topic&lt;/a&gt;.

    &lt;/p&gt;
&lt;/div&gt;


&lt;h2 id="display-html-content-in-read-only-mode"&gt;Display HTML Content in Read-Only Mode&lt;/h2&gt;
&lt;p&gt;Since&amp;nbsp;mobile applications  don&amp;#39;t have much screen space, its good practice to separate item&amp;nbsp;detail info/editing views.&lt;/p&gt;

&lt;p&gt;In this particular example, our .NET MAUI HTML Edit displays rich text in read-only mode on the detail view page (HTML Edit includes an&amp;nbsp;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.HtmlEditor.HtmlEdit.IsReadOnly"&gt;IsReadOnly&lt;/a&gt; property that restricts/permits content editing).&lt;/p&gt;

&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:4%;margin:0px 0px 0px 0px;"&gt;
	&lt;img src="https://community.devexpress.com/blogs/mobile/20240422-HTMLEdit/property-description-overview@2x.png" alt="HTML Edit - Item Detail View" width="30%"&gt;
&lt;/div&gt;

&lt;p&gt;To display content in XAML, specify the &lt;a href="https://docs.devexpress.com/MAUI/404637/html-edit/load-and-obtain-markup#display-content-xaml"&gt;HtmlEdit.HtmlSource&lt;/a&gt; property. For this example, this property is bound to a ViewModel property.&lt;/p&gt;

&lt;h3&gt;Related GitHub Repository Files&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="https://github.com/DevExpress-Examples/maui-html-edit/blob/23.2.3%2B/CS/PropertyDescription/Views/PropertiesDetailPage.xaml#L38" target="_blank"&gt;Views/PropertiesDetailPage.xaml&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="https://github.com/DevExpress-Examples/maui-html-edit/blob/23.2.3%2B/CS/PropertyDescription/ViewModels/PropertyViewModel.cs#L61" target="_blank"&gt;ViewModels/PropertyViewModel.cs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2 id="switch-to-edit-mode-and-modify-description-on-a-separate-page"&gt;Switch to Edit Mode and Modify Descriptions on a Separate Page&lt;/h2&gt;

&lt;p&gt;When editing rich text, you will often need more space to display elements such as&amp;nbsp;toolbars. You will also need to reduce excessive scrolling. It&amp;#39;s for these reasons we recommend the use of a separate screen to edit content.&lt;/p&gt;

&lt;p&gt;If you choose to display our&amp;nbsp;HTML Edit Control in a separate view, you can leverage our built-in adaptive toolbar and use the&amp;nbsp;following&amp;nbsp;content editing actions:
    &lt;/p&gt;&lt;ul&gt;
        &lt;li&gt;font attributes&lt;/li&gt;
        &lt;li&gt;colors&lt;/li&gt;
        &lt;li&gt;lists&lt;/li&gt;
        &lt;li&gt;headers&lt;/li&gt;
        &lt;li&gt;and many more.&lt;/li&gt;
&lt;/ul&gt; Set the &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.HtmlEditor.HtmlEdit.ShowToolbar"&gt;HtmlEdit.ShowToolbar&lt;/a&gt; property to &lt;code&gt;true&lt;/code&gt; to display the toolbar. &lt;p&gt;&lt;/p&gt;

&lt;div style="display:flex;justify-content:center;background-color:#F2F2F2;padding:4%;margin:0px 0px 0px 0px;"&gt;
	&lt;img src="https://community.devexpress.com/blogs/mobile/20240422-HTMLEdit/property-description-editing@2x.png" alt="HTML Edit - Item Editing View" width="30%"&gt;
&lt;/div&gt;

&lt;div class="Note"&gt;
    &lt;p&gt;Editing HTML content with the DevExpress HTML Edit works best if you place the control in a &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Core.SafeKeyboardAreaView"&gt;SafeKeyboardAreaView&lt;/a&gt; container. This container allows you to manage the following:
       &lt;/p&gt;&lt;ul&gt;
           &lt;li&gt;Prevent  HTML content from keyboard overlap.&lt;/li&gt;
           &lt;li&gt;Decrease the height of HTML Edit when you open the device keyboard (to&amp;nbsp;maintain&amp;nbsp;toolbar visibility).&lt;/li&gt;
           &lt;li&gt;Display custom content in the keyboard region to add more space for UI elements. The built-in toolbar uses this feature to display action panels.&lt;/li&gt;
    &lt;/ul&gt; 
&lt;/div&gt;

&lt;p&gt;Once you modify the HTML, call the &lt;a href="https://docs.devexpress.com/MAUI/404637/html-edit/load-and-obtain-markup#retrieve-the-displayed-content"&gt;HtmlEdit.GetHtmlAsync&lt;/a&gt; method to obtain  HTML content and save it to a ViewModel property.&lt;/p&gt;

&lt;h3&gt;Related GitHub Repository Files&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;a href="https://github.com/DevExpress-Examples/maui-html-edit/blob/23.2.3%2B/CS/PropertyDescription/Views/PropertyDescriptionEditView.xaml#L16" target="_blank"&gt;Views/PropertyDescriptionEditView.xaml&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="https://github.com/DevExpress-Examples/maui-html-edit/blob/23.2.3%2B/CS/PropertyDescription/Views/PropertyDescriptionEditView.xaml.cs" target="_blank"&gt;Views/PropertyDescriptionEditView.xaml.cs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Tue, 23 Apr 2024 04:00:00 Z</pubDate>
      <dc:creator>Anthony Sameishchev (DevExpress)</dc:creator>
      <dx:excerpt>In this blog post, I&amp;#39;ll overview the HTML Edit Control and use it to display and edit descriptions of houses in a simple application with a CRUD editing form.</dx:excerpt>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388133</guid>
      <link>https://community.devexpress.com/Blogs/mobile/archive/2024/04/02/net-maui-early-access-preview-v24-1-amp-minor-update-enhancements-v23-2-5.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.net+maui">.net maui</category>
      <category domain="https://community.devexpress.com/Tags/2024">2024</category>
      <category domain="https://community.devexpress.com/Tags/Android">Android</category>
      <category domain="https://community.devexpress.com/Tags/EAP">EAP</category>
      <category domain="https://community.devexpress.com/Tags/iOS">iOS</category>
      <category domain="https://community.devexpress.com/Tags/mobile">mobile</category>
      <category domain="https://community.devexpress.com/Tags/prerelease">prerelease</category>
      <category domain="https://community.devexpress.com/Tags/Roadmap">Roadmap</category>
      <category domain="https://community.devexpress.com/Tags/v24.1">v24.1</category>
      <title>.NET MAUI — Early Access Preview (v24.1) &amp; Minor Update Enhancements (v23.2.5) </title>
      <description>&lt;p&gt;We expect to ship our next major .NET MAUI update (v24.1) in a couple of months. This post outlines the features available in our early access preview (EAP) build and documents features included in our minor update&amp;nbsp;(v23.2.5).&lt;/p&gt;

&lt;h2&gt;Early Access Preview (v24.1)&lt;/h2&gt;

&lt;p&gt;If you expect to use our EAP, make certain to check the “Include prerelease” option within NuGet&amp;#39;s Package Manager to access early access preview features.&lt;/p&gt;

&lt;p&gt;
&lt;img src="https://community.devexpress.com/blogs/mobile/20240328-maui-eap-24-1/nuget-manager.png" alt="DevExpress TreeView for .NET MAUI"&gt;
&lt;/p&gt;



&lt;div class="Note"&gt;&lt;p&gt;Early Access and CTP builds are provided solely for early testing purposes and are not ready for production use. This build can be installed side by side with other major versions of DevExpress products. Please back up your project and other important data before installing Early Access and CTP builds.&lt;/p&gt;

&lt;p&gt;This EAP may not include all features/products we expect to ship in our v24.1 release cycle. As its name implies, the EAP offers an early preview of what we expect to ship in two months.&lt;/p&gt;&lt;/div&gt;

&lt;h3&gt;New TreeView Control&lt;/h3&gt;

&lt;p&gt;v24.1 will ship with a new .NET MAUI TreeView&amp;nbsp;control. Designed to present&amp;nbsp;hierarchical data, our .NET MAUI TreeView allows you to&amp;nbsp;create intuitive and visually appealing user interfaces with ease. With our new .NET MAUI TreeView (DXTreeView), you can quickly visualize files structures, organization relationships, hierarchical data sets, navigation menus, and more.&lt;/p&gt;

&lt;p&gt;DXTreeView ships with the following built-in capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hierarchical and self-referential data support&lt;/li&gt;
&lt;li&gt;Independent and recursive check box support&lt;/li&gt;
&lt;li&gt;Filtering&lt;/li&gt;
&lt;li&gt;Sorting&lt;/li&gt;
&lt;li&gt;Item template support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
&lt;img src="https://community.devexpress.com/blogs/mobile/20240328-maui-eap-24-1/treeview-and-treeview.png" class="small" width="60%" alt="DevExpress TreeView for .NET MAUI"&gt;
&lt;/p&gt;


&lt;h3&gt;New SlideView Control&lt;/h3&gt;

&lt;p&gt;v24.1 ships with a new SlideView component - designed to leverage&amp;nbsp;swipe gestures (right/left or up/down) to navigate between views. Our .NET MAUI SlideView component can help you create a variety of user interface solutions including&amp;nbsp;&amp;nbsp;application&amp;nbsp;galleries or user tutorial screens.&lt;/p&gt;


&lt;video width="936" height="528" autoplay="true" loop="true" muted="true" style="width:936px;"&gt;
&lt;source src="https://community.devexpress.com/blogs/mobile/20240328-maui-eap-24-1/SlideView.mp4" type="video/mp4"&gt;
&lt;/video&gt;


&lt;p&gt;SlideView features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MVVM support (&lt;code&gt;ItemsSource&lt;/code&gt;, &lt;code&gt;ItemTemplate&lt;/code&gt;, &lt;code&gt;ShowNext&lt;/code&gt;/&lt;code&gt;ShowPrevious&lt;/code&gt; commands)&lt;/li&gt;
&lt;li&gt;Item caching for better performance&lt;/li&gt;
&lt;li&gt;Horizontal/vertical orientation&lt;/li&gt;
&lt;li&gt;Looped and animated navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;a href="https://docs.devexpress.com/MAUI/404808/slide-view?v=24.1"&gt;Documentation&lt;/a&gt;

&lt;h3&gt;Scheduler – new Agenda View&lt;/h3&gt;

&lt;p&gt;Our&amp;nbsp;new .NET MAUI AgendaView component allows you&amp;nbsp;to display schedules, events, and appointments for as single day.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Features include:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ability to hide empty time slots to save the screen space&lt;/li&gt;
&lt;li&gt;Appointment and header appearance customization options&lt;/li&gt;
&lt;li&gt;Built-in button to create a new appointment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240328-maui-eap-24-1/agenda-view-overview.png" class="small" width="40%" alt="DevExpress AgendaView for .NET MAUI"&gt;
&lt;/p&gt;

&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Scheduler.AgendaView?v=24.1"&gt;Documentation&lt;/a&gt;


&lt;h3&gt;PDFViewer — Document Signatures&lt;/h3&gt;

&lt;p&gt;With v24.1, users can&amp;nbsp;sign PDF documents via our intuitive user interface (users can draw a signature at a given&amp;nbsp;location or select a predefined signature). Signatures can be selected, moved and resized. Users can also specify&amp;nbsp;ink color and line width.&lt;/p&gt;

&lt;p&gt;To respond to user sign actions, our .NET MAUI PDF Viewer includes the following events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SignatureAdded&lt;/code&gt; / &lt;code&gt;SignatureAdding&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SignatureChanged&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SignatureDelete&lt;/code&gt; / &lt;code&gt;SignatureDeleting&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SignatureSelectionChanged&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;video width="936" height="528" autoplay="true" loop="true" muted="true" style="width:936px;"&gt;
&lt;source src="https://community.devexpress.com/blogs/mobile/20240328-maui-eap-24-1/pdf-Sign.mp4" type="video/mp4"&gt;
&lt;/video&gt;


&lt;h3&gt;PDFViewer — Text Selection&lt;/h3&gt;

&lt;p&gt;Users are now able to select text in a PDF document and highlight or copy it to the clipboard as requirements dictate. To help facilitate selection,&amp;nbsp;we added a selection context menu that appears when text is selected (the menu includes copy and highlight commands).&lt;/p&gt;

&lt;p&gt;You can also interact&amp;nbsp;with selected content via new API methods and events.&lt;/p&gt;


&lt;h3&gt;PDFViewer — Text Formatting Annotations&lt;/h3&gt;

&lt;p&gt;v24.1 gives you the&amp;nbsp;ability to highlight  selected text with different markup text annotations. The following text decorations can be added via the interface or API:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highlight&lt;/li&gt;
&lt;li&gt;Underline&lt;/li&gt;
&lt;li&gt;Strikethrough&lt;/li&gt;
&lt;li&gt;Underline with a wavy line&lt;/li&gt;
&lt;/ul&gt;



&lt;video width="936" height="528" autoplay="true" loop="true" muted="true" style="width:936px;"&gt;
&lt;source src="https://community.devexpress.com/blogs/mobile/20240328-maui-eap-24-1/pdf-Highlight.mp4" type="video/mp4"&gt;
&lt;/video&gt;


&lt;h3&gt;PDFViewer — Graphic Annotations&lt;/h3&gt;

&lt;p&gt;Users can now add annotations to a PDF document, and then comment/collaborate with one another. Our .NET MAUI PDF viewer supports the following annotations:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sticky notes&lt;/li&gt;
&lt;li&gt;Free text&lt;/li&gt;
&lt;li&gt;Ellipses (Circle annotations)&lt;/li&gt;
&lt;li&gt;Rectangles (Square annotations)&lt;/li&gt;
&lt;li&gt;Free-hand drawing&lt;/li&gt;
&lt;/ul&gt;

&lt;video width="936" height="528" autoplay="true" loop="true" muted="true" style="width:936px;"&gt;
&lt;source src="https://community.devexpress.com/blogs/mobile/20240328-maui-eap-24-1/pdf-Annotations.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;p&gt;Note: Our official release should give you the ability to apply all the annotations listed above via the control&amp;#39;s UI.&lt;/p&gt;


&lt;h3&gt;Fltering UI — Predefined Filters&lt;/h3&gt;

&lt;p&gt;v24.1 will ship with&amp;nbsp;a new PredefinedFilterCheckedChipGroupItem component. You can leverage this new UI element to add quick chip filters. Each filter chip allows you to set display text and filter criterion. Common usage scenarios for this filter item include creating favorite user filters or filtering based on a predefined value range.&lt;/p&gt;

&lt;p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240328-maui-eap-24-1/predefined-checked-chip-group.png" class="small" width="40%" alt="DevExpress Filtering UI for .NET MAUI - Predefined filters"&gt;
&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-xml"&gt;
&amp;lt;ContentPage ...
             xmlns:dxe=&amp;quot;clr-namespace:DevExpress.Maui.Editors;assembly=DevExpress.Maui.Editors&amp;quot;&amp;gt;
             &amp;lt;!--...--&amp;gt;
                  &amp;lt;dxe:PredefinedFilterCheckedChipGroupItem Text=&amp;quot;Price&amp;quot; FieldName=&amp;quot;Price&amp;quot; ShowValueCounts=&amp;quot;true&amp;quot;&amp;gt;
                      &amp;lt;dx:PredefinedFilter Text=&amp;quot;$0 - $500&amp;quot; FilterExpression=&amp;quot;?p &amp;lt; 500&amp;quot;/&amp;gt;
                      &amp;lt;dx:PredefinedFilter Text=&amp;quot;$500 - $2000&amp;quot; FilterExpression=&amp;quot;?p &amp;gt;= 500 AND ?p &amp;lt; 2000&amp;quot;/&amp;gt;
                      &amp;lt;dx:PredefinedFilter Text=&amp;quot;$2000+&amp;quot; FilterExpression=&amp;quot;?p &amp;gt;= 2000&amp;quot;/&amp;gt;
                  &amp;lt;/dxe:PredefinedFilterCheckedChipGroupItem&amp;gt;
             &amp;lt;!--...--&amp;gt;
&amp;lt;/ContentPage&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Editors.PredefinedFilterCheckedChipGroupItem?v=24.1"&gt;Documentation&lt;/a&gt;








&lt;h2&gt;Minor Update (v23.2)&lt;/h2&gt;

&lt;h3&gt;New Slider Controls&lt;/h3&gt;

&lt;p&gt;We added two slider controls to our .NET MAUI component suite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Editors.DXSlider"&gt;DXSlider&lt;/a&gt;&lt;/code&gt; — allows users to select a numeric value.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Editors.DXRangeSlider"&gt;DXRangeSlider&lt;/a&gt;&lt;/code&gt; — allows users to select a range of numeric values.&lt;/li&gt;
&lt;/ul&gt;
    
&lt;p&gt;Both controls adhere to the most recent Material Design 3 guideline.&lt;/p&gt;

&lt;p&gt;
&lt;img src="https://community.devexpress.com/blogs/mobile/20240328-maui-eap-24-1/sliders@2x.png" class="small" width="30%" alt="DevExpress Sliders for .NET MAUI"&gt;
&lt;/p&gt;

&lt;p&gt;Features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configurable scale step&lt;/li&gt;
&lt;li&gt;Minimum and maximum values&lt;/li&gt;
&lt;li&gt;Customizable thumbs, tickmarks, and track&lt;/li&gt;
&lt;/ul&gt;


&lt;a href="https://docs.devexpress.com/MAUI/404789/slider-and-rangeslider/index?v=24.1"&gt;Documentation&lt;/a&gt;




&lt;h3&gt;CollectionView — Multi-Column Layout&lt;/h3&gt;

&lt;p&gt;DXCollectionView now supports multiple items in a row/column. Our&amp;nbsp;multi-span layout can simplify design if/when collection view items are displayed as cards (allowing you to display more items on screen).&lt;/p&gt;

&lt;p&gt;For more information, please refer to the following API members:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSpanCount"&gt;ItemSpanCount&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSpacing"&gt;ItemSpacing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSpanSpacing"&gt;ItemSpanSpacing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
&lt;img src="https://community.devexpress.com/blogs/mobile/20240328-maui-eap-24-1/cv-multi-column-layout@2x.png" class="small" width="50%" alt="DevExpress CollectionView for .NET MAUI - Multi-span layout"&gt;
&lt;/p&gt;




&lt;h3&gt;CollectionView — Ripple Effect&lt;/h3&gt;

&lt;p&gt;DXCollectionView&amp;nbsp;now supports ripple effects for tapped items. Ripple animations can help you create more intuitive user experiences. To activate ripple effects, enable the &lt;a href="http://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.UseRippleEffect?v=24.1"&gt;UseRippleEffect&lt;/a&gt; property.&lt;/p&gt;

&lt;p&gt;
&lt;img src="https://community.devexpress.com/blogs/mobile/20240328-maui-eap-24-1/cv-ripple-effect.gif" class="small" width="50%" alt="DevExpress CollectionView for .NET MAUI - Ripple effect"&gt;
&lt;/p&gt;


&lt;h3&gt;CollectionView — Item and Group Separators&lt;/h3&gt;

&lt;p&gt;Separators are common elements and are used in most collections. With our most recent update, you no longer&amp;nbsp;need to add a separator&amp;nbsp;to your item template. This enhancement&amp;nbsp;simplifies the XAML code and template arrangement&amp;nbsp;logic. The&amp;nbsp;following APIs will help you&amp;nbsp;add separators to a DXCollectionView:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.GroupItemSeparatorColor"&gt;GroupItemSeparatorColor&lt;/a&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.GroupItemSeparatorCapMargin"&gt;GroupItemSeparatorCapMargin&lt;/a&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.GroupItemSeparatorThickness"&gt;GroupItemSeparatorThickness&lt;/a&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSeparatorColor"&gt;ItemSeparatorColor&lt;/a&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSeparatorThickness"&gt;ItemSeparatorThickness&lt;/a&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSeparatorCapMargin"&gt;ItemSeparatorCapMargin&lt;/a&gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.CollectionView.DXCollectionView.ItemSeparatorShowBeforeGroup"&gt;ItemSeparatorShowBeforeGroup&lt;/a&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;h3&gt;HTML Edit — Tables&lt;/h3&gt;

&lt;p&gt;Users can now add and edit tables within our .NET MAUI HTML Editor. Like other DevExpress .NET MAUI controls, user interface elements are designed to maximize ease-of-use on mobile devices/form factors.&lt;/p&gt;

&lt;p&gt;
&lt;img src="https://community.devexpress.com/blogs/mobile/20240328-maui-eap-24-1/insert-tables-view.png" class="small" width="30%" alt="DevExpress HTML Edit for .NET MAUI - Inserting tables"&gt;
&lt;/p&gt;

&lt;a href="https://docs.devexpress.com/MAUI/404638/html-edit/modify-html-markup#insert-and-remove-tables"&gt;Documentation&lt;/a&gt;



&lt;h3&gt;DXButton — Ripple Effect&lt;/h3&gt;

&lt;p&gt;We added&amp;nbsp;ripple effect support to DXButton. Enable the &lt;a href="https://docs.devexpress.com/MAUI/DevExpress.Maui.Core.DXButtonBase.UseRippleEffect"&gt;UseRippleEffects&lt;/a&gt; property to activate ripple animations for individual buttons.&lt;/p&gt;



&lt;h3&gt;Target Standard&amp;nbsp;.NET&lt;/h3&gt;

&lt;p&gt;As you may know, the XUnit testing library requires standard .NET 8 (not .NET 8.0 Android/iOS) to be referenced as a target framework within project settings. In previous versions, you could not&amp;nbsp;use our controls in a standard&amp;nbsp;.NET 8 project and therefore you could not&amp;nbsp;use XUnit. With v23.2.5, you can  target standard .NET 8 in projects when using DevExpress .NET MAUI component libraries.&lt;/p&gt;&lt;pre&gt;&lt;code class="language-xml" data-line="3"&gt;&amp;lt;Project Sdk=&amp;quot;Microsoft.NET.Sdk&amp;quot;&amp;gt;
    &amp;lt;PropertyGroup&amp;gt;
        &amp;lt;TargetFrameworks&amp;gt;net8.0;net8.0-android;net8.0-ios&amp;lt;/TargetFrameworks&amp;gt;
        &amp;lt;OutputType Condition=&amp;quot;&amp;#39;$(TargetFramework)&amp;#39; != &amp;#39;net8.0&amp;#39;&amp;quot;&amp;gt;Exe&amp;lt;/OutputType&amp;gt;
        &amp;lt;!-- ... --&amp;gt;
    &amp;lt;/PropertyGroup&amp;gt;
    &amp;lt;!-- ... --&amp;gt;
&amp;lt;/Project&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;a href="https://docs.devexpress.com/MAUI/404781/unit-testing"&gt;Documentation&lt;/a&gt;</description>
      <pubDate>Tue, 02 Apr 2024 04:05:00 Z</pubDate>
      <dc:creator>Kseniya Kuzmina (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388119</guid>
      <link>https://community.devexpress.com/Blogs/mobile/archive/2024/04/01/How-to-Profile-NET-MAUI-Applications-and-Isolate-Performance-Related-Issues.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.net+maui">.net maui</category>
      <category domain="https://community.devexpress.com/Tags/Android">Android</category>
      <category domain="https://community.devexpress.com/Tags/iOS">iOS</category>
      <category domain="https://community.devexpress.com/Tags/maui">maui</category>
      <category domain="https://community.devexpress.com/Tags/mobile">mobile</category>
      <category domain="https://community.devexpress.com/Tags/performance">performance</category>
      <title>How to Profile .NET MAUI Applications and Isolate Performance-Related Issues</title>
      <description>&lt;p&gt;According to 
&lt;a href="https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/page-load-time-statistics/" target="_blank"&gt;Google/SOASTA research&lt;/a&gt;, bounce rates 
increase by 32% when page load takes 1-3 seconds. Though enterprise mobile app users are unlikely to close an application if they encounter unnecessary delays, performance issues may affect perception/overall user experience. Understanding/addressing&amp;nbsp;performance bottlenecks can be challenging (and time consuming)&amp;nbsp;but mastering the process can help enhance app usability/adoption.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In this blog post, I’ll demonstrate a simple technique to profile .NET MAUI applications using&amp;nbsp;&lt;a href="https://marketplace.visualstudio.com/items?itemName=nromanov.dotnet-meteor" target="_blank"&gt;.NET Meteor&lt;/a&gt; and &lt;a href="https://marketplace.visualstudio.com/items?itemName=sransara.speedscope-in-vscode" target="_blank"&gt;Speedscope&lt;/a&gt; VS Code extensions. You can leverage the techniques outlined herein whether using&amp;nbsp;Windows or macOS.&amp;nbsp;&lt;span style="color:#404040;"&gt;If you&amp;#39;d prefer, you can also watch a step-by-step tutorial video on YouTube:&lt;/span&gt;&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/-4VWRt_-PKw?si=5F2EWkGe48EyeDO4" allowfullscreen="" style="width:560px;" referrerpolicy="strict-origin-when-cross-origin"&gt;&lt;/iframe&gt;
&lt;h2 id="step-1-install-tooling"&gt;Step 1: Install Tools&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ll use the following tools in this tutorial:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.visualstudio.com/download" target="_blank"&gt;Visual Studio Code&lt;/a&gt; – a lightweight cross-platform editor. Powered by a few extensions, it offers all the IDE capabilities required to develop .NET MAUI apps, regardless of the OS used.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=nromanov.dotnet-meteor" target="_blank"&gt;.NET Meteor&lt;/a&gt; – a VS Code extension for running, debugging, and profiling&amp;nbsp;.NET MAUI projects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=sransara.speedscope-in-vscode" target="_blank"&gt;Speedscope&lt;/a&gt; – a VS Code extension to render profiling snapshots as a flame graph.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can download .NET Meteor and Speedscope&amp;nbsp;from the &lt;a href="https://marketplace.visualstudio.com/" target="_blank"&gt;Visual Studio Marketplace&lt;/a&gt; or use the “&lt;em&gt;Extensions&lt;/em&gt;” tab in VS Code.&lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Install%20Extensions.png" alt="Install the .NET Meteor and Speedscope VS Code extensions" class="small" style="width:401px;height:286px;"&gt;
&lt;h2 id="step-2-prepare-application"&gt;Step 2: Prepare Application&lt;/h2&gt;
&lt;p&gt;Once necessary tooling is installed, simply open the project you&amp;#39;d&amp;nbsp;like to profile. As you know, VS Code doesn’t use &amp;quot;&lt;em&gt;*.sln&amp;quot;&lt;/em&gt;&amp;nbsp;solution files created in Visual Studio. Therefore, to open your project, use the “&lt;em&gt;Open Folder&lt;/em&gt;” menu item and select the project folder.&lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Open%20Project%20Folder.png" alt="Opening the VS Code .NET MAUI Project" class="small"&gt;
&lt;p&gt;Once open, navigate to the “&lt;em&gt;Run&amp;nbsp;and Debug&lt;/em&gt;” tab and create a “&lt;em&gt;launch.json&lt;/em&gt;” file.&lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Launch%20File.png" alt="Creating the Launch File" class="small" style="width:400px;height:274px;"&gt;
&lt;p&gt;.NET Meteor applies settings for running, debugging, and profiling apps from this file. To profile an application, add a configuration entry with the “&lt;em&gt;profilerMode&lt;/em&gt;” attribute set to “&lt;em&gt;trace&lt;/em&gt;”.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js" data-line-numbers="true" data-line="10-16"&gt;{ 
    &amp;quot;version&amp;quot;: &amp;quot;0.2.0&amp;quot;, 
    &amp;quot;configurations&amp;quot;: [ 
        { 
            &amp;quot;name&amp;quot;: &amp;quot;.NET Meteor Debugger&amp;quot;, 
            &amp;quot;type&amp;quot;: &amp;quot;dotnet-meteor.debugger&amp;quot;, 
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;, 
            &amp;quot;preLaunchTask&amp;quot;: &amp;quot;dotnet-meteor: Build&amp;quot; 
        }, 
        { 
            &amp;quot;name&amp;quot;: &amp;quot;.NET Meteor Profiler&amp;quot;, 
            &amp;quot;type&amp;quot;: &amp;quot;dotnet-meteor.debugger&amp;quot;, 
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;, 
            &amp;quot;profilerMode&amp;quot;: &amp;quot;trace&amp;quot;, 
            &amp;quot;preLaunchTask&amp;quot;: &amp;quot;dotnet-meteor: Build&amp;quot; 
        } 
    ] 
} &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;You can set &lt;span style="color:#404040;"&gt;“&lt;/span&gt;&lt;em style="color:#404040;"&gt;profilerMode&lt;/em&gt;&lt;span style="color:#404040;"&gt;”&lt;/span&gt; to “&lt;/span&gt;&lt;em&gt;gcdump&lt;/em&gt;&lt;span&gt;” for memory profiling, but I’ll describe this mode in a separate blog post.&lt;/span&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;Save the modified &amp;quot;&lt;em&gt;launch.json&amp;quot;&lt;/em&gt;&amp;nbsp;file and select the profiling configuration from the dropdown menu located next to the &amp;quot;&lt;em&gt;Start&amp;quot;&lt;/em&gt;&amp;nbsp;button.&lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Select%20Profiling%20Configuration.png" alt="Select Profiling Configuration" class="small"&gt;
&lt;h2 id="step-3-obtain-profiling-snapshot"&gt;Step 3: Obtain Profiling Snapshot&lt;/h2&gt;
&lt;p&gt;We can now&amp;nbsp;run the application to collect profiling data. Note: Be sure to &amp;quot;Run Without Debugging.&amp;quot;&lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Run%20Without%20Debugging.png" alt="Run the project without debugging" class="small"&gt;
&lt;p&gt;Open the view you&amp;#39;d like to inspect and press the &amp;quot;&lt;em&gt;&lt;strong&gt;Stop&lt;/strong&gt;&lt;/em&gt;&amp;quot; button. To obtain a valid snapshot, it&amp;#39;s important to stop the application using VS Code instead of closing it on the device/emulator.&lt;/p&gt;
&lt;h2 id="step-4-analyze-snapshot"&gt;Step 4: Analyze Snapshot&lt;/h2&gt;
&lt;p&gt;.NET Meteor saves the profiling snapshot to the &amp;quot;*.speedscope.json&amp;quot;&amp;nbsp;file under the &amp;quot;&lt;em&gt;.meteor&amp;quot;&lt;/em&gt;&amp;nbsp;directory. Right-click this file and open it with Speedscope.&lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Open%20With%20Speedscope%20Short.png" alt="Open .NET MAUI VS Code Profile Snapshot with Speedscope" class="small"&gt;
&lt;p&gt;Once open, you will see a flame graph with all .NET functions called when you interacted with the application. The wider a block, the more execution time for the corresponding function. The flame graph automatically groups methods with a similar call stack (it represents aggregated data, reducing the amount of information you need to analyze). Let’s consider the following simplified flame graph as an example:&lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Sample%20Flame%20Graph.png" alt="Simplified Flame Graph" class="small"&gt;
&lt;p&gt;Here, method &lt;em&gt;F1 &lt;/em&gt;calls &lt;em&gt;F2&lt;/em&gt;, which in turn calls &lt;em&gt;F3&lt;/em&gt;. Then, a new &lt;em&gt;F3 &lt;/em&gt;starts and calls &lt;em&gt;F4&lt;/em&gt;. When &lt;em&gt;F4 &lt;/em&gt;is complete, &lt;em&gt;F3 &lt;/em&gt;and &lt;em&gt;F1 &lt;/em&gt;are completed as well. At this point a new &lt;em&gt;F3 &lt;/em&gt;function (green) starts. Because the last&amp;nbsp;&lt;em&gt;F3 &lt;/em&gt;function has a different call stack, it’s not merged with &lt;em&gt;F3 &lt;/em&gt;functions called earlier.&lt;/p&gt;
&lt;p&gt;Let’s take a look at two performance issues I intentionally introduced in my test app.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sample Issue 1: Heavy View Model Initialization &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the following code snippet, I initialize a collection of items in the view model constructor. When each item is added, the &lt;em&gt;Thread.Sleep&lt;/em&gt; method is called causing a delay.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp" data-line-numbers="true" data-line="9"&gt;public class ProblemPageViewModel : BindableBase { 
    //... 
    public ProblemPageViewModel() { 
        LongInitializationOperation(); 
    } 
    void LongInitializationOperation() { 
        Customers = new ObservableCollection&amp;lt;Customer&amp;gt;(); 
        for (int i = 1; i &amp;lt; 200; i++) { 
            Thread.Sleep(10);  
            Customers.Add(new Customer() { ID = i, Name = &amp;quot;Customer&amp;quot; + i }); 
        } 
    } 
} &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here is how this code appears in the flame graph.  &lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Long%20View%20Model%20Initialization.png" alt="Long Test Function Flame Graph"&gt;
&lt;p&gt;As you can see, &lt;em&gt;LongInitializationOperation &lt;/em&gt;is very wide compared to sibling methods which may indicate a potential issue. To focus on a specific method, you can open the “&lt;em&gt;Sandwich&lt;/em&gt;” tab, press “&lt;em&gt;Ctrl + F&lt;/em&gt;” and find this method. In the “&lt;em&gt;Sandwich&lt;/em&gt;” view, you can select a function and see all previous and subsequent methods in a more readable manner. &lt;/p&gt;
&lt;p&gt;Here, you can see that the performance issue is caused by the &lt;em&gt;Thread.Sleep&lt;/em&gt; method. This is evident because we call it every time a new item is added to the &lt;em&gt;Customers&lt;/em&gt; collection. That was a simple example - let’s move on to a more realistic usage scenario.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sample Issue 2: Unoptimized View Layout&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let’s consider the following view with a vertical stack panel and CollectionView: &lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml" data-line-numbers="true" data-line="9-11"&gt;&amp;lt;ContentPage xmlns=&amp;quot;http://schemas.microsoft.com/dotnet/2021/maui&amp;quot; 
             xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2009/xaml&amp;quot; 
             x:Class=&amp;quot;TestPerformanceApp.ProblemPage&amp;quot; 
             xmlns:viewModels=&amp;quot;clr-namespace:TestPerformanceApp.ViewModels&amp;quot; 
             Title=&amp;quot;ProblemPage&amp;quot;&amp;gt; 
    &amp;lt;ContentPage.BindingContext&amp;gt; 
        &amp;lt;viewModels:ProblemPageViewModel/&amp;gt; 
    &amp;lt;/ContentPage.BindingContext&amp;gt; 
    &amp;lt;VerticalStackLayout&amp;gt; 
        &amp;lt;CollectionView ItemsSource=&amp;quot;{Binding Customers}&amp;quot;/&amp;gt; 
    &amp;lt;/VerticalStackLayout&amp;gt; 
&amp;lt;/ContentPage&amp;gt; &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It seems unusual that such a simple layout  causes a delay when loading the view, so what’s wrong with this code?  &lt;/p&gt;
&lt;p&gt;Typically, when a view layout causes performance issues, you will find many “&lt;em&gt;Measure&lt;/em&gt;” methods in the flame graph.&lt;/p&gt;
&lt;img src="https://community.devexpress.com:443/blogs/mobile/20240222-Performance-Profiling/Long%20Measure%20Flame%20Graph.png" alt="Long .NET MAUI View Measure in Flame Graph"&gt;
&lt;p&gt;While the profiler won’t reveal the specific cause of the issue, it’s evident that the problem lies in the view layout. One of the simplest ways to pinpoint the cause of the delay is to comment out XAML code sections until you observe an improvement. However, it&amp;#39;s essential to examine how different view elements function - both separately and together.&lt;/p&gt;
&lt;p&gt;For instance, in the code snippet above, if I comment out the CollectionView, we&amp;#39;d expect a performance improvement, as this is the only relatively complex component in the view. However, CollectionView is a common component, and it would be unusual if it caused such performance issues across all usage scenarios. This suggests that the root cause may be related to its parent panel – VerticalStackLayout. By commenting out the VerticalStackLayout, we see an improvement, indicating that the lag occurs only when VerticalStackLayout is used together with CollectionView.&lt;/p&gt;
&lt;p&gt;The reason behind this particular bottleneck&amp;nbsp;lies in the way VerticalStackLayout measures child elements (infinite height is used for all associated&amp;nbsp;children). As a result, the CollectionView “thinks” that it’s very tall, doesn’t activate the virtualization mechanism, and measures all its elements even if they don’t fit the screen. To resolve the issue, we simply need&amp;nbsp;to replace VerticalStackLayout with a Grid using several rows or &lt;a href="https://docs.devexpress.com/MAUI/404689/layouts/dock-layout" target="_blank"&gt;DXDockLayout&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;While performance optimization can be challenging,&lt;/span&gt;&amp;nbsp;research shows that performance affects the overall user experience and perceived quality of a given&amp;nbsp;application. Bottleneck&amp;nbsp;&lt;span&gt;identification&lt;/span&gt;&amp;nbsp;is the first step in the optimization process and VS Code extensions like&amp;nbsp;&lt;a href="https://marketplace.visualstudio.com/items?itemName=nromanov.dotnet-meteor" target="_blank"&gt;.NET Meteor&lt;/a&gt;&lt;span&gt;&amp;nbsp;and&amp;nbsp;&lt;/span&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=sransara.speedscope-in-vscode" target="_blank"&gt;Speedscope&lt;/a&gt;&amp;nbsp;can be invaluable for those interested in performance optimization.&lt;/p&gt;
&lt;p&gt;Memory leaks are another common performance-related issue, and &lt;a href="https://marketplace.visualstudio.com/items?itemName=nromanov.dotnet-meteor" target="_blank"&gt;.NET Meteor&lt;/a&gt; supports memory profiling as well. We will describe this feature in a separate blog post - please stay tuned!&lt;/p&gt;
&lt;p&gt;Explore more ways to enhance your next great .NET MAUI mobile app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2023/12/06/macos-guide-to-developing-for-net-maui.aspx" target="_blank"&gt;MacOS Guide to Developing for .NET MAUI&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2023/07/21/7-tips-to-boost-net-maui-mobile-app-performance.aspx" target="_blank"&gt;7 Tips to Boost .NET MAUI Mobile App Performance&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2023/10/12/net-maui-mobile-collection-filtering-best-practices.aspx" target="_blank"&gt;.NET MAUI Mobile — Collection Filtering Best Practices&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.devexpress.com/blogs/mobile/archive/2023/10/18/incorporate-crud-operations-into-your-app-with-devexpress-net-maui-collectionview.aspx" target="_blank"&gt;.NET MAUI — Incorporate CRUD Operations in Your Mobile App with DevExpress CollectionView&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Mon, 01 Apr 2024 01:05:00 Z</pubDate>
      <dc:creator>Alexander Russkov (DevExpress)</dc:creator>
    </item>
  </channel>
</rss>