ViewModelLocator not firing up

303 views Asked by At

I have been reading about MVVM (and MVVM Light) lately, so tried to implement in an application with 2 ViewModels.

When I use the ViewModelLocator in the datacontext the Command binding does not work, if I bind the ViewModel to the datacontext of the ViewModel itself it works!

What am I missing here?

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

    public LiveViewViewModel liveViewViewModel
    {
        get
        {
            return ServiceLocator.Current.GetInstance<LiveViewViewModel>();
        }
    }

    public MotionViewModel motionViewModel
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MotionViewModel>();
        }
    }

    public static void Cleanup()
    {
        ClearLiveViewViewModel();
        ClearMotionViewModel();
    }

    public static void ClearLiveViewViewModel()
    {
        ServiceLocator.Current.GetInstance<LiveViewViewModel>().CloseCamera();
        ServiceLocator.Current.GetInstance<LiveViewViewModel>().Cleanup();
    }

    public static void ClearMotionViewModel()
    {
        ServiceLocator.Current.GetInstance<MotionViewModel>().Cleanup();
    }
}

This is the ViewModel code:

public class MotionViewModel : ViewModelBase
{
    private RelayCommand _mocoConnectCommand;
    
    public MotionViewModel()
    {
        if (IsInDesignMode)
        {
            // Code runs in Blend --> create design time data.
        }
        else
        {
            // Code runs "for real"
            Task.Factory.StartNew(() => Initialize());
        }
    }
   
    public RelayCommand MoCoConnectCommand
    {
        get;
        private set;
    }
   
    private void Initialize()
    {
        MoCoConnectCommand = new RelayCommand(MoCoConnect);
    }

    private void MoCoConnect()
    {
        MessageBox.Show("Connection button pressed");
    }
    #endregion
}

This is the XAML View Code:

<UserControl.Resources>
    <ResourceDictionary>
        <vm:ViewModelLocator x:Key="Locator"/>
    </ResourceDictionary>
</UserControl.Resources>

<UserControl.DataContext>
    <Binding Source="{StaticResource Locator}" />
</UserControl.DataContext>

<Button Style="{DynamicResource MahApps.Metro.Styles.MetroButton}" 
            Grid.Column="0" Grid.Row="0"
            Height="30" Width="28" Margin="-1,2,1.333,2.667"
            Command="{Binding MoCoConnectCommand}" >
        <iconPacks:FontAwesome Kind="LinkSolid"/>
</Button>
2

There are 2 answers

0
vernou On BEST ANSWER

The user control's data context is a ViewModelLocator and the button is binding to MoCoConnectCommand property. But the class ViewModelLocator don't have the property MoCoConnectCommand.

I think you need inject MotionViewModel in the user control's data context, like :

<UserControl.Resources>
    <ResourceDictionary>
        <vm:ViewModelLocator x:Key="Locator"/>
    </ResourceDictionary>
</UserControl.Resources>

<UserControl.DataContext>
    <Binding Source="{StaticResource Locator}" Path="motionViewModel" />
</UserControl.DataContext>
0
Akos On

If you want to get into this, try avoiding external libraries. They just make things confusing.

The thing to understand is when you are writing SomeProperty="{Binding PropertyFromViewModel}" it is binding to that usercontrol's DataContext. How to set the datacontext? simple example:

Write this(your file names replace the example ones) into your App.xaml.cs(override onstartup method) and remove "StartupUri" from App.xaml

Window w = new Window();
w.DataContext= new SomethingViewModel();
w.Show();

Now you can bind to public properties from SomethingViewModel in you Window.xaml

What else do you need:

-Implementation of INotifyPropertyChange in a base class(ViewModelBase or whatever name you want) you can keep inheriting for viewmodels and objects that need to refresh the UI

-Implementation of RelayCommand. This can be used to create commands in any viewmodel that can be bound with Binding to commands of controls for example a Button.

Edit: the other answer should fix your problem if you insist on using 3rd party libraries