DevExpress MVVM Services for .NET MAUI
- 5 minutes to read
You can use the following DevExpress MAUI services in MVVM development:
- Popup Dialog Service
- Opens predefined or custom popup dialogs.
- Navigation Service
- Navigates between pages at the ViewModel level.
- Save File Picker Service
- Opens a dialog that allows users to save a file.
- Print Service
- Opens 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:
public static class MauiProgram {
public static MauiApp CreateMauiApp() {
//...
builder.Services.AddTransient<ViewModel>();
}
}
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:
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 whenDXPopupActionSheet
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 whenDXPopupOptionSheet
closes. - ShowCheckBoxOptionSheet(DXPopupSettings, String, String, DXPopupOptionInfo[])
- Opens DXPopupOptionSheet that contains checkboxes. The
ShowCheckBoxOptionSheet
method returns Task, which contains a dialog result, and completes whenDXPopupOptionSheet
closes.
The following example uses the ShowAlert(DXPopupSettings, String, String) method to display an alert with an icon:
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:
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:
<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.
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.
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:
Navigation Service
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.
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:
public class ViewModel {
ISaveFilePicker SaveFilePicker { get; }
public ViewModel(ISaveFilePicker saveFilePicker) {
SaveFilePicker = saveFilePicker;
}
async Task Save() {
await SaveFilePicker.SaveAsync(fileToSave, "HelloWorld.txt", PredefinedFileType.Any);
}
}
Print Service
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:
public class PrintServiceDemoViewModel {
IPrintService PrintService { get; }
public PrintServiceDemoViewModel(IPrintService printService) {
PrintService = printService;
}
async Task Print() {
await PrintService.PrintAsync("BalanceSheet.pdf");
}
}