While working with Caliburn V2 I’ve noticed that there is no default View for the message box. It was a bumpy road figuring out how to add one but I’ve learned a lot.
In this post you can see my solution for this challenge, but the flexibility of the framework allows multiple solutions and you may come up with a different one.
The result of this exercise look like this:
In my case I wanted to warn the user during the Screen closure if the changes have not been saved. The usual place to hook the check is in “CanClose” method:
public override void CanClose(Action<bool> callback) { if (HasChanges) { var result = Show.MessageBox("Current item was not saved. Do you really want to close it?", "Question", new[] { Answer.Ok, Answer.Cancel }); result.Completed += (s, e) => callback(result.Answer == Answer.Ok); result.ExecuteWithDefaultServiceLocator(); } else { callback(true); } } public static class Extensions { public static void ExecuteWithDefaultServiceLocator(this IResult result) { result.Execute(new ResultExecutionContext(IoC.Get<IServiceLocator>(), null, null)); } }
Notice that the result of the “Completed” callback from the MessageBox is used to raise the callback reply for the “CanClose” method.
When I ran the application I’ve received an error from Caliburn that the “QuestionDialogView” was not found. After checking the source I’ve noticed that the View, in fact, is not there. I had to create one. This is my simplified take on the view:
<UserControl ...> <Grid x:Name="LayoutRoot"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="40"/> </Grid.RowDefinitions> <ContentControl x:Name="FirstQuestion" Grid.Row="0"> <ContentControl.ContentTemplate> <DataTemplate> <TextBlock x:Name="Text" Text="{Binding Text}" TextWrapping="Wrap" Style="{StaticResource DefaultTextBlockStyle}" /> </DataTemplate> </ContentControl.ContentTemplate> </ContentControl> <ItemsControl x:Name="Buttons" Grid.Row="1" HorizontalAlignment="Right" Margin="0,10,0,0"> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Button Content="{Binding Content, Converter={StaticResource upperCase}}" cal:Message.Attach="{Binding Action}" Width="70" /> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl> </Grid> </UserControl>
After the view was defined – it had to be registered in the IOC to be found. This is how I did it in the bootstrapper:
builder.With.PresentationFramework() .Using(x => x.ViewLocator<DefaultViewLocator>()) .Configured(x => x.AddNamespaceAlias("Caliburn.ShellFramework", "MyProject.Common.Views"))
BTW: in the following article you can find a full View definition for the MessageBox. When I’ve replaced my XAML with the XAML from this article – I’ve received exactly the same result:
http://caliburn.codeplex.com/wikipage?title=ISupportCustomShutdown