1

I have a view, which initializes a viewmodel inside the windows resources. Further more I give my grid the DataContext.

My question is, how I can add a command to my windows closing event keeping mvvm in memory? I tried the version of this post: Handling the window closing event with WPF / MVVM Light Toolkit ... but its not working using an event-trigger, because I can't access the viewmodel from outside my grid, so I can't access my command.

Any solution for my problem?

Greetings

Jannik

Edit: Here's my xaml:

<Window x:Class="WpfApplication1.Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModels="clr-namespace:WpfApplication1.ViewModels"
    xmlns:converter="clr-namespace:WpfApplication1.Converter"
    Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <viewModels:MainWindowViewModel x:Key="ViewModel"/>
    </Window.Resources>

    <Grid DataContext="{StaticResource ViewModel}">...</Grid>
</Window>
Community
  • 1
  • 1
Jannik
  • 2,310
  • 6
  • 32
  • 61
  • What is the DataContext of your Window referring to? – Bizhan Nov 06 '13 at 11:09
  • Its not refering to anything, but I cant refer to my ViewModel, because its initialized AFTER the refer-location – Jannik Nov 06 '13 at 11:41
  • You have to be more specific then. Is the datacontext of the grid is set through code behind or through xaml? – Bizhan Nov 06 '13 at 11:46
  • I dont have anything in the code behind, it is bound to the grid-datacontext-attribute. – Jannik Nov 06 '13 at 11:47
  • If you set the DataContext of your window to {StaticResource ViewModel} you should be able to store it somewhere when closing command is executing. – Bizhan Nov 06 '13 at 11:57
  • How you would solve it on the example above? – Jannik Nov 06 '13 at 12:08

2 Answers2

1

You can reference to members of a static resource this way:

Command="{Binding Path=CloseCommand, Source={StaticResource ViewModel}}"

Here's the complete test project. I used a text box with a binding to ensure data is saved.

<Window x:Class="WpfApplication1.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewModels="clr-namespace:WpfApplication1.ViewModels"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <viewModels:MainWindowViewModel x:Key="ViewModel"/>
    </Window.Resources>

    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Closing">
            <i:InvokeCommandAction Command="{Binding Path=CloseCommand, Source={StaticResource ViewModel}}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid DataContext="{StaticResource ViewModel}">
        <TextBox Text="{Binding Txt, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</Window>

In ViewModel code, I used a static reference to store data (LastInstance). you can replace it with your own method.

Also I used Command which is a custom implementation of ICommand. If you want I can add the complete implementation here.

    public MainWindowViewModel()
    {
        //save or load here...
        if (LastInstance != null) Txt = LastInstance.Txt;
        CloseCommand = new Command(o => LastInstance = this);
        //...
    }

    public static ViewModel LastInstance;

    //Txt Dependency Property
    public string Txt
    {
        get { return (string)GetValue(TxtProperty); }
        set { SetValue(TxtProperty, value); }
    }
    public static readonly DependencyProperty TxtProperty =
        DependencyProperty.Register("Txt", typeof(string), typeof(ViewModel), new UIPropertyMetadata(null));
    //CloseCommand Dependency Property
    public Command CloseCommand
    {
        get { return (Command)GetValue(CloseCommandProperty); }
        set { SetValue(CloseCommandProperty, value); }
    }
    public static readonly DependencyProperty CloseCommandProperty =
        DependencyProperty.Register("CloseCommand", typeof(Command), typeof(ViewModel), new UIPropertyMetadata(null));
Bizhan
  • 16,157
  • 9
  • 63
  • 101
0

The typical approach to this problem is to have a MainViewModel and set the DataContext of you Window to it. Then define other viewModels in the MainViewModel.

<Window>
    <Grid DataContext="{Binding MyGridViewModel}">
    </Grid>
    <DockPanel DataContext="{Binding AnotherViewModel}">
    </DockPanel>
</Window>

in MainWindow constructor:

this.DataContext = new MainViewModel();

in MainViewModel constructor:

this.MyGridViewModel = new OtherViewModel();

This way you have many options to find the desired object through viewModel references.

Bizhan
  • 16,157
  • 9
  • 63
  • 101