Binding Commands to Button Inside ItemTemplate

1.4k Views Asked by At

Hello I am trying to bind a command to a button inside a LongListSelector's ItemTemplate. But facing binding problems. Here are my codes-

XAML

<DataTemplate x:Key="ItemTemplate">
        <StackPanel Height="108" Width="308" Margin="6,6">
            <TextBlock Text="{Binding Name}" Foreground="red"></TextBlock>
            <TextBlock Text="{Binding Type}" Foreground="red"></TextBlock>
            <Button Content="add to emergency" Foreground="White" Background="red" Command="{Binding Path=DataContext.MyViewModelCommand}"/>
        </StackPanel>
    </DataTemplate>

Command

public class ActionCommand : ICommand
{
    private readonly Action _action;

    public ActionCommand(Action action)
    {
        _action = action;
    }

    public void Execute(object parameter)
    {
        _action();
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;
}

ViewModel

public class HspitalVM:INotifyPropertyChanged
{
    public HspitalVM()
    {
        MyViewModelCommand = new ActionCommand(DoSomething);
    }

    public ICommand MyViewModelCommand { get; private set; }
    private void DoSomething()
    {

    }
}

The command works okay for bare buttons, but doesn't work inside ItemTemplate. Please guide me

3

There are 3 best solutions below

0
On BEST ANSWER

Finally the answer

XAML (for the page)

<phone:PhoneApplicationPage
DataContext="{Binding HspitalVM, Source={StaticResource Locator}}" >

XAML (for the control)

<Button x:Name="button" Content="add to emergency" Foreground="White"  Background="#FFF7203C" Command="{Binding HspitalVM.GiveDetails, Mode=OneWay}" DataContext="{Binding Source={StaticResource Locator}}" CommandParameter="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"/>

ViewModel

public RelayCommand<object> GiveDetails { get; private set; }

public HspitalVM()
    {
        hspitalList=ReadToObject();
        GiveDetails = new RelayCommand<object>(DoSomething);
    }

 private void DoSomething(object param)
    {
        var fetchedCountry = (Hspital)param;

        MessageBox.Show("The country name is " + fetchedCountry.Name);
    }
1
On

Mostly its because the button gets bound to the item DataContext and not your ViewModel DataContext you should modify your command binding to somthing like the following :

Command="{Binding Path=DataContext.MyViewModelCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}

The x:Type shall be the parent type that your ViewModel DataContext is set to, it can be Page or a UserControl or any Container, basicly the Control that has your ViewModel DataContext.

And your command has to have a parameter since you will be acting on the item itself, just like the following

 CommandParameter="{Binding}"

This means that the command paramer is the item that the button was clicked on in your View, you can react on it in the ViewModel by adding its reference to another List or removing it, depending on what you want to do.

0
On

The best solution in case of Windows Phone would be using mvvmlight toolkit and using the viewmodellocator class as a source and binding the correct command through that, in this case you can use event to command behavior if needed.

You can see http://msdn.microsoft.com/en-us/magazine/dn237302.aspx for more details.

And if you don't want to use mvvmlight toolkit you can look into this blog that shows ways to bind RelativeSource Binding with FindAncestor mode.

http://blog.thekieners.com/2010/09/08/relativesource-binding-with-findancestor-mode-in-silverlight/

Hope it helps. :)