I'm trying to write some ContentDialog
with ViewModel
.
I'm not using default buttons. I'm using my customized set of buttons. (Including close button placed on top right corner)
So I need to close this dialog somehow in the ViewModel
but I can't do this because I should pass the ContentDialog
into the ViewModel
.
Here is my ContentDialog
s content:
<Grid HorizontalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="1*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Height="32">
<Button Width="32px" Height="32px"
HorizontalAlignment="Right"
Command="{x:Bind ViewModel.CancelCommand, Mode=OneWay}"
CommandParameter="{Binding ElementName=addDeviceDialog}"
Style="{ThemeResource CommandBarFlyoutEllipsisButtonStyle}">
<FontIcon Width="16px" Height="16px" FontSize="10px" Glyph="" />
</Button>
</Grid>
<Grid Grid.Row="1">
</Grid>
<Grid Grid.Row="2" Margin="0 20 0 0">
<Button Width="219"
HorizontalAlignment="Right"
Command="{x:Bind ViewModel.AddCommand}"
Content="Add"
Style="{ThemeResource AccentButtonStyle}" />
</Grid>
</Grid>
and here is my ViewModel
:
public partial class AddDeviceDialogViewModel : ObservableRecipient
{
public IRelayCommand AddCommand
{
get;
}
public IRelayCommand CancelCommand
{
get;
}
public AddDeviceDialogViewModel()
{
AddCommand = new RelayCommand(AddDevice);
CancelCommand = new RelayCommand(Cancel);
}
public void AddDevice() // AddDevice(ContentDialog dialog)
{
// Here I need to add my business logic
if (AddedSuccessfully)
{
// dialog.Hide(); I don't wanna pass ContentDialog to it's ViewModel.
// Close this dialog somehow.
}
else
{
// Show validation errors.
}
}
public async void Cancel() // Cancel(ContentDialog dialog)
{
// dialog.Hide(); I don't wanna pass ContentDialog to it's ViewModel.
// Close dialog somehow.
}
}
I think default implementation of the ContentDialog
has an internal EventHandler
which calls .Hide()
to close this dialog.
As I mentioned in my comment, I'd do this without a ViewModel, but if you the ViewModel anyway, this is one way to close the ContentDialog
from its ViewModel.
ContentDialogContent.xaml
<Page
x:Class="ContentDialogWithViewModelExample.ContentDialogContent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:ContentDialogWithViewModelExample"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid>
<Button
Command="{x:Bind ViewModel.CloseDialogCommand}"
Content="Close" />
</Grid>
</Page>
ContentDialogContent.xaml.cs
public sealed partial class ContentDialogContent : Page
{
public ContentDialogContent()
{
InitializeComponent();
ViewModel.CloseRequested += ViewModel_CloseRequested;
}
public event EventHandler? CloseRequested;
public ContentDialogContentViewModel ViewModel { get; } = new();
private void ViewModel_CloseRequested(object? sender, EventArgs e)
{
CloseRequested?.Invoke(this, EventArgs.Empty);
}
}
ContentDialogContentViewModel.cs I'm using the CommunitToolkit.Mvvm NuGet package here.
public partial class ContentDialogContentViewModel : ObservableObject
{
public event EventHandler? CloseRequested;
[RelayCommand]
private void CloseDialog()
{
CloseRequested?.Invoke(this, EventArgs.Empty);
}
}
Then use the dialog like this:
private async void ShowDialog_Click(object sender, RoutedEventArgs e)
{
ContentDialog dialog = new()
{
XamlRoot = XamlRoot
};
ContentDialogContent contentDialogContent = new();
contentDialogContent.CloseRequested += (s, e) => dialog.Hide();
dialog.Content = contentDialogContent;
ContentDialogResult result = await dialog.ShowAsync();
}