12

I am new in Caliburn Micro and learn it from this helloworld example. In the example there are only 2 views (.xaml) of type Application and UserControl, and 1 view model.

I avoid to use code behind. Therefore I have only view and view model. I want to know how to catch the window close event of my helloworld application so I can handle it in view model. My target: when user is going to close the app by pressing close [x] button on top-right corner the app gives feedback to the user.
I have read about IViewAware and IScreen, but I find no specific example related to my question.

A simple sample code for view and view model are highly appreciated. Thanks in advance.

PS. I use VS2013, C#.

MagB
  • 2,131
  • 5
  • 28
  • 54

4 Answers4

16

What you can do is in your View you can attach Caliburn Micro by using

cal:Message.Attach="[Event Closing] = [Action OnClose($eventArgs)]"

So it will look like

<Window cal:Message.Attach="[Event Closing] = [Action OnClose($eventArgs)]">

And on your ViewModel you can just define a public method that says OnClose with CancelEventArgs as the parameter and you can handle it from there.

123 456 789 0
  • 10,565
  • 4
  • 43
  • 72
  • I don't have view of type Window. My views has only type Application and UserControl. If I use your statement in UserControl I get error: The name "Message" does not exist in the namespace "clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro" – MagB Jul 11 '14 at 14:58
  • I found out, I need to use Caliburn.Micro.Platform – MagB Jul 11 '14 at 15:04
  • Well, UserControl has no Closing event. It seems I must have Window type view or it needs a ShellView. – MagB Jul 11 '14 at 15:23
  • 2
    Yes it should be `Window` or anything that has a `Closing` event – 123 456 789 0 Jul 11 '14 at 15:24
10

If your ViewModel inherits Screen, Caliburn Micro has some methods that you can override like

protected override void OnDeactivate(bool close); 

this is called when a screen is closed or deactivated or

public override void CanClose(Action<bool> callback)

you can check CanClose usage here

Community
  • 1
  • 1
gcores
  • 12,376
  • 2
  • 49
  • 45
3

If you are using the BootstrapperBase class you can use:

protected override void OnExit(object sender, EventArgs e)
1

You're looking for a way to bind an Event to a Command. The typical approach here is to use the EventToCommand behavior from MVVMLight.

Example usage (from the linked article):

<StackPanel Background="Transparent">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Tap">
      <command:EventToCommand
        Command="{Binding Main.NavigateToArticleCommand,
          Mode=OneWay,
          Source={StaticResource Locator}}"
        CommandParameter="{Binding Mode=OneWay}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
  <!--...-->
</StackPanel>

For your specific scenario, you are not using MVVMLight. Since that framework is open-source, you could copy the implementation of EventToCommand into your own project, or - more simply - you can use the InvokeCommandAction, which is part of the System.Windows.Interactivity.dll library, included with Expression Blend.

Example of InvokeCommandAction:

<TextBox x:Name="TicketNumber">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="KeyDown">
            <i:InvokeCommandAction Command="{Binding OpenTicketCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</TextBox>

Lastly, this entire MVVM dogma that you "can't have any code behind" has been shot down time | and | time again (that last link is particularly relevant). MVVM is supposed to be unit-testable, and separates the "View logic" from the "Business logic." The "Close" event is admittedly a bit of a gray area between View and Business logic. But, if you can write an event handler in your code behind, which invokes your ViewModel's appropriate method or command, and if you can unit test that code, then you're as good as gold. Don't worry about removing all traces of code-behind from your project.

Community
  • 1
  • 1
BTownTKD
  • 7,911
  • 2
  • 31
  • 47
  • Thank for your quick reply, but I don't use MVVM Light right now. I am sure caliburn micro has different way, probably easier way. PS. I have used MVVM Light before. – MagB Jul 11 '14 at 14:30