Reputation: 103
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>
Upvotes: 0
Views: 359
Reputation: 220
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
Upvotes: 0
Reputation: 7590
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>
Upvotes: 2