Back to Devexpress

DevExpress MVVM Services for .NET MAUI

maui-405356-mvvm-services.md

latest11.9 KB
Original Source

DevExpress MVVM Services for .NET MAUI

  • Jun 27, 2025
  • 5 minutes to read

You can use the following DevExpress MAUI services in MVVM development:

Popup Dialog ServiceOpens predefined or custom popup dialogs.Navigation ServiceNavigates between pages at the ViewModel level.Save File Picker ServiceOpens a dialog that allows users to save a file.Print ServiceOpens the default print dialog.

These services are automatically added to the default Dependency Injection (DI) container. To access a service within your ViewModel , you need to register the ViewModel and define a constructor that accepts corresponding interfaces:

csharp
public static class MauiProgram { 
    public static MauiApp CreateMauiApp() { 
        //... 
        builder.Services.AddTransient<ViewModel>(); 
    } 
}
csharp
public class ViewModel {
    public ViewModel(INavigationService navigationService, IPrintService printService, ISaveFilePicker saveFilePickerService) { 
        //navigationService.GoToAsync(...); 
        //printService.PrintAsync(...); 
        //saveFilePickerService.SaveAsync(...); 
    } 
}

If you implement a custom service, register it in the DI container to replace the predefined service:

csharp
public static class MauiProgram { 
    public static MauiApp CreateMauiApp() { 
        //... 
        builder.Services.AddSingleton<INavigationService, NavigationServiceEx>(); 
    } 
} 
public class NavigationServiceEx : NavigationService { }

Pop-Up Dialog Service

The IDXPopupService allows you to display predefined and custom pop-up dialogs when a user taps the corresponing button.

Built-in Pop-Up Dialogs

The IDXPopupService includes the following predefined dialogs:

  • An alert message with text, icon, and buttons.
  • An alert message with custom content.
  • An action sheet with or without a Cancel button.
  • A single-choice action sheet with radio buttons.
  • A multiple-choice action sheet with checkboxes.

To use these dialogs, you need to inject the IDXPopupService into your ViewModel through the Dependency Injection and call one of the following methods:

ShowAlert(DXPopupSettings, String, String)Shows the DXPopupDialog and returns the Task that completes when the DXPopupDialog closes.ShowActionSheet(DXPopupSettings, String, DXPopupActionInfo[])Opens DXPopupActionSheet. The ShowActionSheet method returns Task, which contains a dialog result, and completes when DXPopupActionSheet closes.ShowRadioOptionSheet(DXPopupSettings, String, String, DXPopupOptionInfo[])Opens DXPopupOptionSheet that contains radio buttons. The ShowRadioOptionSheet method returns the Task, which contains a dialog result, and completes when DXPopupOptionSheet closes.ShowCheckBoxOptionSheet(DXPopupSettings, String, String, DXPopupOptionInfo[])Opens DXPopupOptionSheet that contains checkboxes. The ShowCheckBoxOptionSheet method returns Task, which contains a dialog result, and completes when DXPopupOptionSheet closes.

The following example uses the ShowAlert(DXPopupSettings, String, String) method to display an alert with an icon:

csharp
public class PopupServiceDemoViewModel {
    readonly IDXPopupService PopupService;

    public PopupServiceDemoViewModel(IDXPopupService popupService) {
        PopupService = popupService;
    }

    Task ShowAlertWithIcon() {
        var res = await popupService.ShowAlert(
            settings: new DXPopupSettings() {
                Title = "Reset Settings ?",
                Message = "This will reset your app preferences back to their default settings.",
                TitleIcon = icon
            },
            ok: "Accept",
            cancel: "Cancel");
    }
}

Custom Pop-Up Dialogs

To display a custom pop-up dialog, inherit your dialog from DXPopupDialog as follows:

csharp
public partial class LoginPopup : DXPopupDialog {
    public LoginPopup() {
        InitializeComponent();
    }
}

The created dialog class allows you to configure all properties available in DXPopupDialog, such as AllowScrim, OKButtonText, and CancelButtonText:

xaml
<dx:DXPopupDialog
    ...
    Title="DevExpress"
    Message="Please enter your login and password"
    AllowScrim="{Binding AllowScrim}"
    OKButtonText="Login"
    OKButtonCommand="{Binding LoginCommand}"
    CancelButtonText="Cancel"
    CloseOnOKButton="False"
    CloseOnCancelButton="True">

    <dx:DXStackLayout>
        <dx:TextEdit
                    LabelText="Login"
                    Text="{Binding Login.Value}"
                ... />
        <dx:PasswordEdit
                    LabelText="Password"
                    Text="{Binding Password.Value}"
                .../>
    </dx:DXStackLayout>
</dx:DXPopupDialog>

Create a ViewModel that implements the IDXPopupViewModel interface required to access methods declared in the IDXPopup interface. IDXPopup allows you to close the pop-up dialog in code.

csharp
public class LoginPopupViewModel : DXObservableObject, IDXPopupViewModel {
    string login;
    public string Login { get => login; set => SetProperty(ref login, value); }
    public bool Result { get; private set; }
    public AsyncRelayCommand LoginCommand { get; }
    public LoginPopupViewModel() {
        //...
        LoginCommand = new(DoLogin);
    }
    async Task DoLogin() {
        //...
        Result = true;
        popup!.Close();
    }

    IDXPopup IDXPopupViewModel.Popup { set => popup = value; }
    IDXPopup? popup;
}

To retrieve the custom popup dialog result, use ViewModel properties. For example, to get the login result and entered credentials, use Result and Login properties.

csharp
async Task ShowCustomPopup() {
    var vm = await PopupService.ShowPopup<LoginPopupViewModel>();
    if (!vm.Result) {
       Console.WriteLine($"Login={vm.Login}");
    }
}

Refer to the following example for more information:

View Example: DevExpress MVVM UI for .NET MAUI

Shell.Current.GoToAsync() is a universal .NET MAUI navigation method that you can call anywhere in your code. However, if you call the GoToAsync() method directly at the ViewModel level, the Model becomes dependent on a particular navigation implementation. Such strong dependencies between the ViewModel and platform-dependent code break the MVVM pattern and complicate unit testing.

To implement MVVM-compliant navigation between Views , you can inject NavigationService into your ViewModel.

csharp
public class ViewModel { 
    INavigationService NavigationService { get; } 
    public ViewModel(INavigationService navigationService) { 
        NavigationService = navigationService; 
    } 

    void ShowDetailForm() { 
        var parameters = new Dictionary<string, object>(); 
        parameters["NavigationParameter"] = NavigationParameter; 
        NavigationService.GoToAsync("DetailView", parameters, false); 
    } 
}

Like the standard GoToAsync() method, the NavigationService.GoToAsync() method allows you to specify the target View name and navigation parameters. In addition, you can obtain the current View through the CurrentLocation property.

Save File Picker Service

The SaveFilePicker service opens a standard dialog that allows users to select the save file name, location, and format:

csharp
public class ViewModel { 
    ISaveFilePicker SaveFilePicker { get; } 
    public ViewModel(ISaveFilePicker saveFilePicker) { 
        SaveFilePicker = saveFilePicker; 
    } 

    async Task Save() { 
        await SaveFilePicker.SaveAsync(fileToSave, "HelloWorld.txt", PredefinedFileType.Any); 
    } 
}

The PrintService is designed to trigger a printing dialog. You can call the PrintAsync(Stream, String, PrintContentType) or PrintAsync(String, String, PrintContentType) method and pass the target document name as a parameter:

csharp
public class PrintServiceDemoViewModel {    
    IPrintService PrintService { get; }

    public PrintServiceDemoViewModel(IPrintService printService) {
        PrintService = printService;
    }
    async Task Print() {
        await PrintService.PrintAsync("BalanceSheet.pdf");
    }
}