Hooking up command in View to ViewModel

Topics: Prism v2 - WPF 3.5
Dec 3, 2009 at 12:35 AM

Hi,

 I am trying to figure out how to hook up commands declared in my view to my view model.  

 I have a ProductCollectionView.Xaml, which has

<Button Content="Refresh" Command="{Binding Path=RefreshCommand}"/>

In the ProductCollectionViewModel.cs I have

public class ProductCollectionViewModel : ViewModelBase 
{
     private ICommand RefreshCommand { get; set; }
 
public ProductCollectionViewModel(IProductDataService dataService, IEventAggregator eventAggregator)
 base()
{
      this.RefreshCommand = new DelegateCommand<string>(this.Refresh);
}

private void Refresh(string  vm) 
{
   int productID = 1; 
   ProductSelected(this, new DataEventArgs<int>(productID));
} 

How do I hook up the RefreshCommand to execure the Refresh method in the ProductCollectionViewModel?

thanks,

<font size="2" color="#0000ff"><font size="2" color="#0000ff">

Arun

</font></font><font size="2" color="#0000ff">

 

</font>

 

Dec 3, 2009 at 2:04 AM

I think your problem is that you're declaring the RefreshCommand property as private, try making it public as below:

public ICommand RefreshCommand { get; set; }


        
    
Dec 3, 2009 at 3:28 AM

Hi,

Thanks for pointing that out.  I had overlooked that.  Could you tell me or point me to a link that explains how the view knows to route the event to the viewmodel ?

Arun

Dec 3, 2009 at 6:36 AM

I'm not sure of a link off the top of my head, but generally I set the datacontext of the view to the viewmodel.

So that when you bind to the command in your view (Binding Path=RefreshCommand), and with the datacontext set to your viewmodel, it will look for the "RefreshCommand" property in your viewmodel.

 

Dec 3, 2009 at 7:11 AM

Oh ok. makes sense

Thanks

Arun

Dec 26, 2009 at 4:04 PM
Edited Jan 1, 2010 at 6:21 PM

EDIT: I've added  a simplified example of exposing the view model methods directly:  download

 

There is a harder but somehow more beautiful way(IMHO) on doing this in convention over configuration style: As you know Reflection.Emit namespace allows you to create specialized class instances at runtime via CLR, so you can implement a generic factory that will create ICommand from your ViewModel methods using Reflection:

public class CommandAdapterFactory<T> where T: ViewModelBase
{

Object CreateCommandAdapter(){ some CLR magic to create class  with ICommand props}

}

So your regular code will look like this:

Binding path will change to Commands.<MethodName>

<Button Content="Refresh" Command="{Binding Path=Commands.Refresh}"/>  

 

public class ProductCollectionViewModel : ViewModelBase 
{
private Object Commands {get;set;} //we'll bind commands to this adapter

public ProductCollectionViewModel(IProductDataService dataService, IEventAggregator eventAggregator)
base()
{
Commands = CommandAdapterFactory<ProductCollectionViewModel>();//we use factory to create specialized command adapter
}

[MyCommandAttribute]//attribute showing to your factory that it's a command
private void Refresh(string vm)
{
int productID = 1;
ProductSelected(this, new DataEventArgs<int>(productID));
}
}