0

Assuming that I have a tabcontrol with several tabitems and the implementation is based on this and using usercontrols for each tabs like this. MVVM light is also used.

How to notify in a proper way (mvvm) the tabitems that the application is closing by clicking on (x) in order to save data for each tab? I know how to handle a closing event in the MainWindow which hosts the tabitems but I don't know how to notify the UserControl(actually its viewmodel) for each tabitem. Any idea? Moreover if the tabitem is not selected and showed on the screen, will be notified for the closing?

Solved

I followed the @3615 solution in the comments of this question. Using Messenger which is based on Mediator pattern. So my MainViewModel listens for a window closing event and broadcasts the information to the tabitems.

Community
  • 1
  • 1
gts13
  • 1,048
  • 1
  • 16
  • 29
  • 1
    When main window closes it can call some Cleanup method on MainViewModel, which will iterate your tab items and call Cleanup on each of them. Another way would be using Mediator patter, in MVVMLight implemented by Messenger. So from MainViewModel you publish an event, and in each Tab you listen to that event. – 3615 Apr 27 '17 at 11:12
  • Perhaps making in tabItemsBaseClass IsChanged and IsValid properties, and when eather of those 2 gives back 'true' then prevent application from closing, and user can check those tabs. And based on those 2 properties you can change tab header background color and that way user will be notified that he made some changes and can act on them. – ivica.moke Apr 27 '17 at 11:31
  • and like @Krom said, i have also used event, to be precisely i've used PRISM EventAggregator to publish and subscribe on specific event to check for changes in mainViewModel. – ivica.moke Apr 27 '17 at 11:35

3 Answers3

0

I had the same problem some time ago and I fix it using events, so, when a tab is created, the MainVM attach to the UserControl event which is launched when the tab must be closed, and then the MainVM receives the event and close the tab because it has the access to the OpenedTabs collection.

Krom
  • 98
  • 6
0

Any idea?

You could handle the CollectionChanged event of the ObservableCollection<T> that is bound to the ItemsSource property of the TabControl.

The data object that is represented by the UserControl should be removed from this collection when the (x) button is clicked.

mm8
  • 163,881
  • 10
  • 57
  • 88
0

if your are MVVM, tabs have a corresponding "Document" viewmodel in the "Main". When exit, check your viewmodel if they are dirty and need to be saved. When closing a document from the tab cross, send a message to the "Main" which is responsible for managing and closing documents...

private void MetroWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        MainViewModel mvm = this.DataContext as MainViewModel;
        if ( !mvm.Close() )
            e.Cancel = true;
        else
        {
            ....
        }
    }

and

public MainViewModel(string param)
    {
        Messenger.Default.Register<DocumentViewModel>(this, ViewModelMessages.DocumentRequestClose,
            (DocumentViewModel o) =>
            {
                this.Documents.Remove(o);
                o.Cleanup();

                if( this.Documents.Count == 0)
                    ActiveDocument = null;
            });
GCamel
  • 612
  • 4
  • 8
  • to be honest I don't get your answer very well - forgive me I am almost beginner in mvvm light + wpf. How exactly the viewmodels of the tabitems get notified from this example? Shouldn't be the "Messenger.Default.Register..." in the viewmodel of each tabitem to listen for closing msg? – gts13 Apr 28 '17 at 09:51
  • Well, all depends of your soft architecture, but here "MainViewModel" is managing a collection of doc "this.Documents" and is responsible for it : creating, saving, closing...here a sample a bit more complex : https://github.com/TheCamel/CBR – GCamel Apr 29 '17 at 14:49