2

I'm trying to use the MVVM Light framework with an "OnLoad" view function, so that when the form is loaded a function from the ViewModel is executed.

I have achieved that, following the examples of several links:

https://stackoverflow.com/a/3409801/2794484 http://aslamhadi.com/add-onload-event-in-wpf-mvvm/ https://social.msdn.microsoft.com/Forums/vstudio/en-US/b4d2afe6-4c28-44e5-98a5-b7ba30fec220/how-to-capture-window-loaded-event-in-view-model-when-using-mvvm?forum=wpf

My view has:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding LoadWindowCommand, Mode=OneWay}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

And my ViewModel:

    public TestViewModel()
    {
        LoadWindowCommand = new RelayCommand(OnLoadWindowCommand);
    }

    public RelayCommand LoadWindowCommand { get; private set; }
    private void OnLoadWindowCommand()
    {
        //put your code here
    }

It works, but using the methods of any of the links, raises me a binding error at runtime:

System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=LoadWindowCommand; DataItem=null; target element is 'EventToCommand' (HashCode=4875788); target property is 'Command' (type 'ICommand')

How can I avoid this error?


Update, I have updated all my code as your recommendations.

MainView:

<Window x:Class="MvvmLight1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:GalaSoft_MvvmLight_Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
       xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:ignore="http://www.ignore.com"
        xmlns:local="clr-namespace:MvvmLight1.ViewModel"
        mc:Ignorable="d ignore"
        Title="MVVM Light Application" Height="300" Width="300">
    <Window.Resources>
        <local:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
    </Window.Resources>
    <Window.DataContext>
        <!--Move DataContext binding there-->
        <Binding Path="Main" Source="{StaticResource Locator}"/>
    </Window.DataContext>
    <Grid>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Loaded">
                <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding LoadWindowCommand, Mode=OneWay}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Grid>
</Window>

ViewModel:

class MainWindowViewModel : ViewModelBase
{
    public MainWindowViewModel()
    {
        LoadWindowCommand = new RelayCommand(OnLoadWindowCommand);
    }

    public RelayCommand LoadWindowCommand { get; private set; }
    private void OnLoadWindowCommand()
    {
        Debug.WriteLine("Loaded!");
    }
}

ViewModelLocator

class ViewModelLocator
{
    public ViewModelLocator()
    {
        Main = new MainWindowViewModel();
    }

    public MainWindowViewModel Main { get; private set; }
}

And I have commented the following lines in the App.xaml:

<!--<Application.Resources>
    <vm:ViewModelLocator x:Key="Locator"
                         d:IsDataSource="True" />
</Application.Resources>-->    

But in my "Output" Windows I continue seeing:

....
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=LoadWindowCommand; DataItem=null; target element is 'EventToCommand' (HashCode=44967810); target property is 'Command' (type 'ICommand')
'MvvmLight1.vshost.exe' (Administrado (v4.0.30319)): se cargó 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework.Aero\v4.0_4.0.0.0__31bf3856ad364e35\PresentationFramework.Aero.dll', se omitió la carga de símbolos. Se optimizó el módulo y se habilitó la opción 'Solo mi código'.
'MvvmLight1.vshost.exe' (Administrado (v4.0.30319)): se cargó 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\UIAutomationProvider\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationProvider.dll', se omitió la carga de símbolos. Se optimizó el módulo y se habilitó la opción 'Solo mi código'.
'MvvmLight1.vshost.exe' (Administrado (v4.0.30319)): se cargó 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\UIAutomationTypes\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationTypes.dll', se omitió la carga de símbolos. Se optimizó el módulo y se habilitó la opción 'Solo mi código'.
Loaded!

The only difference I can see with your code, is in the namespaces references of the MainWindow:

xmlns:mvvm_light_cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform"

And mine:

xmlns:GalaSoft_MvvmLight_Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"

If I add your namespace it returns and error trying to resolve "GalaSoft.MvvmLight.Platform"

Any suggestion?

Community
  • 1
  • 1
Josep B.
  • 587
  • 1
  • 6
  • 16
  • `DataItem=null` means there's no DataContext. Did you bind view model to view correctly? Do other bindings work? – icebat Feb 19 '16 at 10:55
  • Yes, All bindings work fine. To avoid problems I added the onload methods inside a MVVM Light project started from scratch – Josep B. Feb 19 '16 at 11:09

1 Answers1

2

Ok, I've got it. Problem is that you are trying to get the Locator resource before it is initialize. Just put your DataContext binding after resources section. Here is the code:

MainWindow.xaml

<Window x:Class="MvvmLight1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:GalaSoft_MvvmLight_Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras"
       xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:ignore="http://www.ignore.com"
        xmlns:local="clr-namespace:MvvmLight1.ViewModel"
        mc:Ignorable="d ignore"
        Title="MVVM Light Application" Height="300" Width="300">
    <Window.Resources>
        <local:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
    </Window.Resources>
    <Window.DataContext>
        <!--Move DataContext binding there-->
        <Binding Path="Main" Source="{StaticResource Locator}"/>
    </Window.DataContext>
    <Grid>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Loaded">
                <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding LoadWindowCommand, Mode=OneWay}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Grid>
</Window>

MainViewModel.cs

namespace MvvmLight1.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        public MainViewModel()
        {
            LoadWindowCommand = new RelayCommand(OnLoadWindowCommand);
        }

        public RelayCommand LoadWindowCommand { get; private set; }
        private void OnLoadWindowCommand()
        {
            Debug.WriteLine("Loaded!");
        }
    }
}

ViewModelLocator.cs

namespace MvvmLight1.ViewModel
{
    public class ViewModelLocator
    {

        public ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
            SimpleIoc.Default.Register<MainViewModel>();
        }

        public MainViewModel Main
        {
            get
            {
                return ServiceLocator.Current.GetInstance<MainViewModel>();
            }
        }
    }
}
Anton Danylov
  • 1,491
  • 10
  • 16
  • the ViewModel was set in the properties of the MainVindow "DataContext="{Binding Main, Source={StaticResource Locator}}". I have copied all of your code and in the "Output" window I have the following messages: System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=LoadWindowCommand; DataItem=null; target element is 'EventToCommand' (HashCode=7530847); target property is 'Command' (type 'ICommand') Loaded! – Josep B. Feb 19 '16 at 12:24
  • Ok, thanks, now it is clear. Please have a look at the updated answer. – Anton Danylov Feb 19 '16 at 12:49
  • It continues returning the same error. I added your answer in my question. I only see one difference of the namespace (you can see it in my question). Thanks – Josep B. Feb 19 '16 at 13:25
  • I've noticed, that MVVMlight created a folder ViewModel under a project that contains 2 files, MainViewModel.cs and ViewModelLocator.cs and they are empty by default. I've implemented MainWindowViewModel in top-level namespace, while autogenerated MainViewModel and ViewModelLocator were in MvvmLight1.ViewModel namespace. Try to change xmlns:local="clr-namespace:MvvmLight1.ViewModel" to xmlns:local="clr-namespace:MvvmLight1" in your Window header. – Anton Danylov Feb 19 '16 at 14:57
  • My MainWindowViewModel resides en the "MvvmLight1.ViewModel" namespace, and my ViewModelLocator resides also in the "MvvmLight1.ViewModel" namespace. I deleted the old code regarding ViewModelLocator and MainWindowViewModel to avoid problems. – Josep B. Feb 19 '16 at 15:03
  • Tried to make my solution as close to yours as possible, but still can't reproduce. There could be 2 possible problems: with DataContext initialization and with namespaces, in other case everything should be fine. Updated my answer with MVVMLight implementation, maybe it will help. – Anton Danylov Feb 19 '16 at 15:34
  • Also I've downgraded MVVMLight from 5.20.0 verson to 4.2.32.7 so EventToCommand class is declared in GalaSoft.MvvmLight.Extras and not in GalaSoft.MvvmLight.Platform. Maybe there is some issue with EventToCommand in GalaSoft.MvvmLight.Extras.WPF4. You may also try to download MVVMLight from NuGet. – Anton Danylov Feb 19 '16 at 15:41
  • Thanks for your effort. I updated MVVM Light to version 5.20.0. I copied again all your code, now the namespaces are right. Unfortunately, the binding error isn't solved. I found this workaround to avoid this problem: "http://stackoverflow.com/a/18465023/2794484" – Josep B. Feb 19 '16 at 16:16
  • Ok, using FallbackValue is a good solution in such case. Strange that this binding error was so hard to reproduce on my environment. – Anton Danylov Feb 19 '16 at 16:28