--- uid: Uno.Features.Dialogs --- # Dialogs > [!TIP] > This article covers Uno-specific information for dialog controls in Uno Platform. For a full description of the feature and instructions on using it, see [Dialog controls | Microsoft Learn](https://learn.microsoft.com/windows/apps/design/controls/dialogs-and-flyouts/dialogs). * The `Microsoft.UI.Xaml.Controls.ContentDialog` class provides a XAML-based and highly customizable user dialog. * The `Windows.UI.Popups.MessageDialog` represents a legacy dialog which provides less control over UI. ## Using `ContentDialog` The recommended way to display user dialogs is via the `Microsoft.UI.Xaml.Controls.ContentDialog` class. ```csharp ContentDialog noWifiDialog = new ContentDialog { Title = "No WiFi connection", Content = "Check your connection and try again.", CloseButtonText = "OK" }; // Make sure to set the XamlRoot! noWifiDialog.XamlRoot = anyLoadedControl.XamlRoot; ContentDialogResult result = await noWifiDialog.ShowAsync(); ``` It is crucial to set the `XamlRoot` property before calling `ShowAsync`. This way the dialog will become associated with the visual tree. `XamlRoot` can be retrieved from any loaded control in your window (e.g. a `Button`, your `Page`, etc.). > [!WARNING] > Only one ContentDialog can be open per thread at a time. Attempting to open two ContentDialogs will throw an exception, even if they are trying to open in separate AppWindows. ### Opening a `ContentDialog` from a Model/ViewModel When you want to open a `ContentDialog` from a Model or ViewModel, you can pass the `XamlRoot` from the view to the model or view model by creating a service (e.g., `IXamlRootProvider`) that is initialized at the start of the app with the XamlRoot of the main window. Here is a more detailed example of how to display a `ContentDialog` with result handling: ```csharp private async Task DisplayDeleteFileDialog() { ContentDialog deleteFileDialog = new ContentDialog { Title = "Delete file permanently?", Content = "If you delete this file, you won't be able to recover it. Do you want to delete it?", PrimaryButtonText = "Delete", CloseButtonText = "Cancel" }; deleteFileDialog.XamlRoot = anyLoadedControl.XamlRoot; ContentDialogResult result = await deleteFileDialog.ShowAsync(); // Delete the file if the user clicked the primary button. // Otherwise, do nothing. if (result == ContentDialogResult.Primary) { // Delete the file. } else { // The user clicked the CloseButton, pressed ESC, Gamepad B, or the system back button. // Do nothing. } } ``` ### [MVVM](#tab/mvvm) If you are using the MVVM pattern, you can use the `AsyncRelayCommand` from the Uno Platform to bind the command to the dialog display method. Here is an example of how to bind the command to the dialog display method in the ViewModel: ```csharp public MainViewModel() { DisplayDeleteFileDialogCommand = new AsyncRelayCommand(DisplayDeleteFileDialog); } // ... public ICommand DisplayDeleteFileDialogCommand { get; } private async Task DisplayDeleteFileDialog() { // ... } ``` ### [MVUX](#tab/mvux) If you are using the MVUX pattern, you don't need to specify the Command. Instead, you can directly call the dialog display method in your view, it is generated automatically in `BindableModel`: ```csharp public async Task DisplayDeleteFileDialogCommand() { // ... } ``` --- To bind the command to a button in your view, you can use the following code snippets: ### [XAML](#tab/xaml) ```xml