This project is read-only.

How to do clean up in CloseCurrentViewAction

Jul 1, 2013 at 3:58 PM
My program uses CloseCurrentViewAction to close the screens (in a Metro style application). I would like to call some clean up code when the users closes the screen. Is there a way I can get CloseCurrentViewAction to call another method?

Thanks,
Sue
Jul 1, 2013 at 5:59 PM
Edited Jul 1, 2013 at 6:42 PM
Sue,

If you can elaborate on what you need to do (close connections, indicate if this only needs to be run in certain conditions, etc.) we may be able to give you a more appropriate answer.

There are 2 ways that I know of.

1) Using ViewResultEventSinks from Control.cs. Markus can probably explain this much better than I.
2) Create code to respond to an action.
The CloseCurrentViewAction is great if you want to close a non-editable view since there is usually no clean up required.

Here is an example of a save method that checks for changes and then closes the view. It might get you started because you can just change this to handle your specific situation:

You will note that it saves the data, etc. and then, if the response from the save is successful, it closes the view:
public void Save()
{
    AsyncWorker.Execute(() =>
            {
                var response = new SaveCustomerResponse();
                ServiceClient.Call<ICustomerService>(service =>
                        {
                            var request = new SaveCustomerRequest();
                            Mapper.Map(this, request.CustomerToSave);
                            response = service.SaveCustomer(request);
                        });
                return response;
            },
            response =>
            {
                if (response.Success)
                    Controller.CloseViewForModel(this);
                else
                    MessageBox.Show(response.FailureInformation);
            }, this);
}
This could be created by the constructor via the following code:
Actions.Add(new ViewAction("Save",
    execute: (a, o) => Save(),
    brushResourceKey: "CODE.Framework-Icon-Save"));
Note: this code is essentially from their online class - so if you have taken one of those, you probably have this code already.


Take care,

Fletcher
Jul 1, 2013 at 6:46 PM
Edited Jul 1, 2013 at 6:49 PM
Sue,

Here is an example of using the EventSinks (also from their class):
private void Edit(IViewAction a, object o)
{
    if (SelectedCustomer == null)
        return;
    var sinks = new ViewResultEventSinks();
    sinks.ViewClosed += (s, e) =>
    {
        Controller.Notification("Refreshing customer list...");
        LoadData();
    };
    Controller.Action("Customer", "Edit", new
    {
        Id = SelectedCustomer.Identifier1
    }, sinks);
}
Here it checks if an id has been selected (this would be a property in the model) and, if one is available, passes it to the Edit method of the controller so that view may be opened.

Note the middle statement that specifies that, when the edit view is closed, that the customer data should be re-loaded. Is this what you want?

Take care,

Fletcher
Jul 1, 2013 at 7:22 PM
Fletcher, thank you very much for your detailed and quick response!

Your first reply is what I was after. I just need to clear the database session when the user closes the view. I didn't know that I could close the view by just using the controller to call CloseViewForModel. That's my dumb mistake... I just didn't think to check the controller.

Thanks,
Sue
Jul 1, 2013 at 10:05 PM
These suggestions are all correct.

In addition, if you inherit your view model from one of our view model classes (either ViewModel or StandardViewModel), then the view model raises a Closing (before it is closed) and a Closed event (after it is closed), so you can out your code in there as well. Of course you do not have to use our view model classes and can create your own from scratch. In that case, you can implement our IClosable interface and in that case, the close events will also be triggered on your view model. (Basically, when a view is closed, the framework checks if the model associated with the view implements IClosable, and if so, raises events on it).

Another option would be to subclass the close view action, or create your own view action to close the current view. The close view model is really just a simple convenience class. Here's all the code in the Execute method:
private void ExecuteCommand(IViewAction a, object s)
{
    Controller.CloseViewForModel(_model);
}
So all it does is store a reference to the model (which it gets in the constructor) and then uses the controller method to close the view associated with the current model. You can do exactly the same in your own view action if you want, but also add additional code there if needed.


Markus
Jul 2, 2013 at 5:30 AM
Markus,

Funny I should read this as I am just now in the process of creating a subclass of the ViewModel class so I can add some methods that all my UI forms will need. Your comment about "...then the view model raises a Closing (before it is closed) and a Closed event (after it is closed), " got me intrigued.

How does it do it in a class based on a subclass of ViewModel but not on a class based on ViewModel? Or are you just implying that I could then add those events?

Not a big deal, just curious.

Thanks,

Fletcher
Jul 2, 2013 at 2:24 PM
It's based on the interface. The framework looks at whatever object you have used as the model (and you can use anything, really.... it doesn't have to be one of our view models... although it usually is) and it then checks if that class implements IClosable. If it does, it fires the events that it now knows the object must have, since the interface defines them.


Markus