How to: Work with Dialogs
This guide covers creating and showing modal dialogs, returning results, and building custom dialog windows.
Showing a Dialog Window
Create a dialog window and show it modally with ShowDialog<T>:
var dialog = new ConfirmDialog();
dialog.DataContext = new ConfirmDialogViewModel("Delete this item?");
// ShowDialog returns a result when the dialog closes
bool? result = await dialog.ShowDialog<bool?>(parentWindow);
if (result == true)
{
DeleteItem();
}
The parentWindow parameter sets the owner. On desktop platforms, the dialog appears centered over the owner window and prevents interaction with it until closed.
Creating a Dialog Window
A dialog is a regular Window with some typical settings:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyApp.Views.ConfirmDialog"
Title="Confirm"
Width="400" Height="200"
WindowStartupLocation="CenterOwner"
CanResize="False"
ShowInTaskbar="False">
<Grid RowDefinitions="*,Auto" Margin="20">
<TextBlock Grid.Row="0" Text="{Binding Message}"
TextWrapping="Wrap" VerticalAlignment="Center" />
<StackPanel Grid.Row="1" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8">
<Button Content="Cancel" Command="{Binding CancelCommand}" />
<Button Content="OK" Command="{Binding ConfirmCommand}" />
</StackPanel>
</Grid>
</Window>
Closing with a result
Close the dialog and return a value using Window.Close(result):
public partial class ConfirmDialog : Window
{
public ConfirmDialog()
{
InitializeComponent();
}
}
public partial class ConfirmDialogViewModel : ObservableObject
{
private readonly Window _dialog;
public string Message { get; }
public ConfirmDialogViewModel(Window dialog, string message)
{
_dialog = dialog;
Message = message;
}
[RelayCommand]
private void Confirm() => _dialog.Close(true);
[RelayCommand]
private void Cancel() => _dialog.Close(false);
}
Set up the dialog and its view model:
var dialog = new ConfirmDialog();
var vm = new ConfirmDialogViewModel(dialog, "Delete this item?");
dialog.DataContext = vm;
bool? result = await dialog.ShowDialog<bool?>(this);
Alternative: Close from code-behind
If you prefer to keep the close logic in the view:
public partial class ConfirmDialog : Window
{
public ConfirmDialog()
{
InitializeComponent();
}
private void OnOkClick(object? sender, RoutedEventArgs e)
{
Close(true);
}
private void OnCancelClick(object? sender, RoutedEventArgs e)
{
Close(false);
}
}
Returning Complex Results
Return any object from a dialog:
// Dialog that returns a selected color
var dialog = new ColorPickerDialog();
Color? selectedColor = await dialog.ShowDialog<Color?>(parentWindow);
if (selectedColor is not null)
{
ApplyColor(selectedColor.Value);
}
In the dialog:
[RelayCommand]
private void Select()
{
_dialog.Close(SelectedColor);
}
[RelayCommand]
private void Cancel()
{
_dialog.Close(null);
}
Getting the Parent Window
To show a dialog from a view model or UserControl where you do not have a direct reference to the parent window:
// From a UserControl's code-behind
var window = TopLevel.GetTopLevel(this) as Window;
if (window is not null)
{
var result = await dialog.ShowDialog<bool?>(window);
}
From a view model, pass the window through a service or parameter:
public interface IDialogService
{
Task<bool> ShowConfirmAsync(string message);
Task<string?> ShowInputAsync(string prompt);
}
public class DialogService : IDialogService
{
private readonly Window _mainWindow;
public DialogService(Window mainWindow)
{
_mainWindow = mainWindow;
}
public async Task<bool> ShowConfirmAsync(string message)
{
var dialog = new ConfirmDialog();
dialog.DataContext = new ConfirmDialogViewModel(dialog, message);
var result = await dialog.ShowDialog<bool?>(_mainWindow);
return result == true;
}
}
File and Folder Dialogs
Use the IStorageProvider service for file and folder picker dialogs:
var topLevel = TopLevel.GetTopLevel(this);
if (topLevel is null) return;
var storage = topLevel.StorageProvider;
// Open file picker
var files = await storage.OpenFilePickerAsync(new FilePickerOpenOptions
{
Title = "Select a File",
AllowMultiple = false,
FileTypeFilter = new[]
{
new FilePickerFileType("Text Files") { Patterns = new[] { "*.txt" } },
new FilePickerFileType("All Files") { Patterns = new[] { "*" } },
}
});
if (files.Count > 0)
{
var file = files[0];
await using var stream = await file.OpenReadAsync();
// Read file contents
}
// Save file picker
var file = await storage.SaveFilePickerAsync(new FilePickerSaveOptions
{
Title = "Save File",
SuggestedFileName = "document.txt",
FileTypeChoices = new[]
{
new FilePickerFileType("Text Files") { Patterns = new[] { "*.txt" } },
}
});
if (file is not null)
{
await using var stream = await file.OpenWriteAsync();
// Write file contents
}
See Storage Provider for the full API.
Preventing Dialog Close
Handle the Closing event to prevent the dialog from closing (e.g., when there are unsaved changes):
dialog.Closing += (sender, e) =>
{
if (HasUnsavedChanges)
{
e.Cancel = true;
// Optionally show a confirmation
}
};
Overlay Dialogs (In-Window)
For dialogs that appear within the window (not as a separate OS window), use an overlay panel:
<Grid>
<!-- Main content -->
<StackPanel Margin="20">
<Button Content="Show Dialog" Command="{Binding ShowDialogCommand}" />
</StackPanel>
<!-- Dialog overlay -->
<Border Background="#80000000"
IsVisible="{Binding IsDialogVisible}">
<Border Background="White" CornerRadius="8"
HorizontalAlignment="Center" VerticalAlignment="Center"
Padding="24" MinWidth="300" BoxShadow="0 8 16 0 #40000000">
<StackPanel Spacing="16">
<TextBlock Text="Confirm Action" FontWeight="Bold" FontSize="18" />
<TextBlock Text="Are you sure?" />
<StackPanel Orientation="Horizontal" Spacing="8"
HorizontalAlignment="Right">
<Button Content="Cancel" Command="{Binding HideDialogCommand}" />
<Button Content="OK" Command="{Binding ConfirmCommand}" />
</StackPanel>
</StackPanel>
</Border>
</Border>
</Grid>
This approach works on all platforms including WebAssembly where separate windows are not supported.
See Also
- Window Management: Show, ShowDialog, and window lifecycle.
- Storage Provider: File and folder picker dialogs.
- Commanding: Binding buttons to commands.