I am trying to use the Mahapps dialog boxes in my project but have been unable to get them to work when trigger from a ReactivUI command in my ViewModel.In the view's XAML, I have registered the dialog.
xmlns:dialogs="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
dialogs:DialogParticipation.Register="{Binding}"
I also have a button which is bound to the ShowDialog command.
this.BindCommand(viewModel, vm => vm.ShowDialog, x => x.button);
Finally, in my ViewModel, I have the RxUI command and the dialogcoordinator instance set.
public MainWindowViewModel(IDialogCoordinator dialogCoordinator)
{
_dialogCoordinator = dialogCoordinator;
ShowDialog = ReactiveCommand.CreateFromTask(async () =>
{
await _dialogCoordinator.ShowMessageAsync(this, "Message from VM", "MVVM based dialogs!");
});
ShowDialog.ThrownExceptions.Subscribe(ex => Console.WriteLine(ex.ToString()));
}
No matter what I have tried it always throw the same error which is
System.InvalidOperationException: Context is not registered. Consider using DialogParticipation.Register in XAML to bind in the DataContext.
I am not sure if there is anything else needed to get the dialog to work or if I am just using the commands in RxUI incorrectly
I had the same problem with another MVVM framework (MVVM Light Toolkit). But the framework doesn't seem the problem. It's a matter of timing. The DialogCoordinator isn't accessable from the constructor. I personally moved all the code from the constructor to RelayCommand that is being fired
<controls:MetroWindow
x:Class="UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
dialog:DialogParticipation.Register="{Binding}"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}"
d:DataContext="{d:DesignInstance vm:MainViewModel}"
mc:Ignorable="d">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ContentRendered">
<i:InvokeCommandAction Command="{Binding StartupCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
I tried different events like Loaded, which worked in some cases but "ContentRendered" always worked in the VM I have the following code:
public ICommand StartupCommand
{
get
{
return new RelayCommand(async ()=>
{
this.AccountName = await
dialogCoordinator.ShowInputAsync(this, "Welcome", "Please insert your account name");
});
}
}
So basically it seems to be not yet registered directly but after the content is loaded it is. (In this example i used ShowInputAsync but it should work the same with ShowMessageAsync)
It does seem to be a timing issue - when I first started playing with this, I got it to work by setting the VM's DialogCoordinator instance from the View's Loaded event, rather than it's constructor.
I've put together a minimal working application demonstrating this at https://github.com/dwarry/ReactiveUiMahAppsDialog. It uses ReactiveUi's normal Interaction mechanism to trigger displaying the dialog. In keeping with that, I've put this in the View, but I don't see why it couldn't be adapted to do it from the ViewModel if you'd rather. One other thing to be aware of is that you need to wait for the dialog to close before leaving the Interaction Handler, or ReactiveUI will throw an UnhandledInteractionException.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With