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




