.NET MAUI Embedding - DevExpress .NET MAUI Controls
The controls from DevExpress .NET MAUI Controls can be used in an Uno Platform application via .NET MAUI Embedding.
Sample App
An existing sample app that showcases the controls is available here.
Installation
The DevExpress .NET MAUI Controls are currently available free of charge. However, in order to access the NuGet packages you do need to create an account at DevExpress website.
Once you have an account with DevExpress, you need to visit the Your DevExpress NuGet Feed URL page to retrieve a NuGet feed that's associated with your account. You can either add this as a NuGet feed in Visual Studio or use a nuget.config file.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="DevExpress Private Feed" value="[your NuGet feed goes here]" />
</packageSources>
</configuration>
Getting Started
Create a new application using the
unoapptemplate, enabling .NET MAUI Embedding. In this case, we're going to use the Blank template (-preset blank) and include .NET MAUI Embedding support (-maui).dotnet new unoapp -preset blank -maui -o MauiEmbeddingAppRemove the
net7.0,net7.0-maccatalystand,net7.0-windows10.0.19041.0target frameworks from both the MauiEmbeddingApp and MauiEmbeddingApp.MauiControls projects. Also, removenet7.0-maccatalystfrom the MauiEmbeddingApp.Mobile project, and remove the MauiEmbeddingApp.Windows project. The DevExpress .NET MAUI Controls only supports iOS and Android.Next, add a reference to
DevExpress.Maui.DataGridto the MauiEmbeddingApp.MauiControls project.In the
AppBuilderExtensionsclass, onMauiEmbeddingApp.MauiControlsproject, update theUseMauiControlsextension method to call theUseDevExpressmethod.using DevExpress.Maui; namespace MauiEmbeddingApp; public static class AppBuilderExtensions { public static MauiAppBuilder UseMauiControls(this MauiAppBuilder builder) => builder .UseDevExpress() .ConfigureFonts(fonts => { fonts.AddFont("MauiEmbeddingApp/Assets/Fonts/OpenSansRegular.ttf", "OpenSansRegular"); fonts.AddFont("MauiEmbeddingApp/Assets/Fonts/OpenSansSemibold.ttf", "OpenSansSemibold"); }); }
Adding DataGridView Control
Update the EmbeddedControl.xaml in the
MauiEmbeddingApp.MauiControlsproject with the following XAML that includes theDataGridViewcontrol.<?xml version="1.0" encoding="utf-8" ?> <ContentView x:Class="MauiEmbeddingApp.MauiControls.EmbeddedControl" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:dxg="clr-namespace:DevExpress.Maui.DataGrid;assembly=DevExpress.Maui.DataGrid"> <dxg:DataGridView ItemsSource="{Binding Employees}"> <dxg:DataGridView.Columns> <dxg:TextColumn FieldName="Name" Caption="Name" /> <dxg:TextColumn FieldName="Position" Caption="Job"/> </dxg:DataGridView.Columns> </dxg:DataGridView> </ContentView>Note
You may notice that the
Bindingmarkup extension is used on some properties. TheMauiEmbeddingcan handle bindings between Maui Controls and UnoPlatform, just make sure the property in theBindingexpression matches the property on your ViewModel.Update the EmbeddedControl.xaml.cs with the following code.
namespace MauiEmbeddingApp.MauiControls; public partial class EmbeddedControl : ContentView { public EmbeddedControl() { InitializeComponent(); } }It's time to create the ViewModel that will hold the properties that will be data bound to the
DataGridViewControlcontrol. InMauiEmbeddingAppproject, create a new folder calledViewModelsand add a new class calledMainViewModel. This class will have the following code:namespace MauiEmbeddingApp.ViewModels; public class MainViewModel { public IReadOnlyList<Employee> Employees { get; }= new EmployeeData().Employees; }And let's create the
Employeemodel and mock it.public enum AccessLevel { Admin, User } public class Employee { public Employee(string name) { this.Name = name; } public string Name { get; } public DateTime BirthDate { get; set; } public DateTime HireDate { get; set; } public string? Position { get; set; } public string? Address { get; set; } public string? Phone { get; set; } public AccessLevel Access { get; set; } public bool OnVacation { get; set; } } public class EmployeeData { void GenerateEmployees() { ObservableCollection<Employee> result = new ObservableCollection<Employee>(); result.Add( new Employee("Nancy Davolio") { BirthDate = new DateTime(1978, 12, 8), HireDate = new DateTime(2005, 5, 1), Position = "Sales Representative", Address = "98122, 507 - 20th Ave. E. Apt. 2A, Seattle WA, USA", Phone = "(206) 555-9857", Access = AccessLevel.User, OnVacation = false } ); result.Add( new Employee("Andrew Fuller") { BirthDate = new DateTime(1965, 2, 19), HireDate = new DateTime(1992, 8, 14), Position = "Vice President, Sales", Address = "98401, 908 W. Capital Way, Tacoma WA, USA", Phone = "(206) 555-9482", Access = AccessLevel.Admin, OnVacation = false } ); result.Add( new Employee("Janet Leverling") { BirthDate = new DateTime(1985, 8, 30), HireDate = new DateTime(2002, 4, 1), Position = "Sales Representative", Address = "98033, 722 Moss Bay Blvd., Kirkland WA, USA", Phone = "(206) 555-3412", Access = AccessLevel.User, OnVacation = false } ); result.Add( new Employee("Margaret Peacock") { BirthDate = new DateTime(1973, 9, 19), HireDate = new DateTime(1993, 5, 3), Position = "Sales Representative", Address = "98052, 4110 Old Redmond Rd., Redmond WA, USA", Phone = "(206) 555-8122", Access = AccessLevel.User, OnVacation = false } ); result.Add( new Employee("Steven Buchanan") { BirthDate = new DateTime(1955, 3, 4), HireDate = new DateTime(1993, 10, 17), Position = "Sales Manager", Address = "SW1 8JR, 14 Garrett Hill, London, UK", Phone = "(71) 555-4848", Access = AccessLevel.User, OnVacation = true } ); result.Add( new Employee("Michael Suyama") { BirthDate = new DateTime(1981, 7, 2), HireDate = new DateTime(1999, 10, 17), Position = "Sales Representative", Address = "EC2 7JR, Coventry House Miner Rd., London, UK", Phone = "(71) 555-7773", Access = AccessLevel.User, OnVacation = false } ); result.Add( new Employee("Robert King") { BirthDate = new DateTime(1960, 5, 29), HireDate = new DateTime(1994, 1, 2), Position = "Sales Representative", Address = "RG1 9SP, Edgeham Hollow Winchester Way, London, UK", Phone = "(71) 555-5598", Access = AccessLevel.User, OnVacation = false } ); result.Add( new Employee("Laura Callahan") { BirthDate = new DateTime(1985, 1, 9), HireDate = new DateTime(2004, 3, 5), Position = "Inside Sales Coordinator", Address = "98105, 4726 - 11th Ave. N.E., Seattle WA, USA", Phone = "(206) 555-1189", Access = AccessLevel.User, OnVacation = true } ); result.Add( new Employee("Anne Dodsworth") { BirthDate = new DateTime(1980, 1, 27), HireDate = new DateTime(2004, 11, 15), Position = "Sales Representative", Address = "WG2 7LT, 7 Houndstooth Rd., London, UK", Phone = "(71) 555-4444", Access = AccessLevel.User, OnVacation = false } ); Employees = result; } public ObservableCollection<Employee> Employees { get; private set; } public EmployeeData() { GenerateEmployees(); } }The final step is to add the
MainViewModelas theDataContextof theMainPage.xamlfile. The finalMainPage.xamlfile will look like this:<Page x:Class="MauiEmbeddingApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MauiEmbeddingApp.ViewModels" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Page.DataContext> <local:MainViewModel /> </Page.DataContext> <StackPanel> <embed:MauiHost xmlns:controls="using:MauiEmbeddingApp.MauiControls" xmlns:embed="using:Uno.Extensions.Maui" Source="controls:EmbeddedControl" /> </StackPanel> </Page>Now the project is good to go! Press F5 and you should see the
DataGridViewcontrol working as expected.
App Render Output
Android:
iOS:

