WPF : How can i call a command from inside a DataTemplate?

Jul 9, 2014 at 11:56 AM
Hi! I am quite a newbie in WPF and I am creating a User Control that has a DataTemplate, which is Dynamically populated. This DataTemplate contains a bunch of controls like buttons and other DataGrids. I want to know how am I supposed to bind the button's command to a relaycommand in my ViewModel? Here are some of the code snippets:
<UserControl.DataContext>
        <Binding Path="UpdateDevices"  Source="{StaticResource Locator}"/>
 </UserControl.DataContext>
<DataTemplate x:Key="ListBoxDataTemplate">
            <Border>
                <Label Background="White" HorizontalContentAlignment="Stretch">
                    <StackPanel Width="Auto" HorizontalAlignment="Stretch">
                        <Grid HorizontalAlignment="Stretch">
                            <Grid.ColumnDefinitions>
                               ....
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                ...
                            </Grid.RowDefinitions>
                            <Button Grid.Column="0" Grid.Row="0" Width="35" Height="35" Background="White" Foreground="White" 
                                    BorderThickness="0" BorderBrush="White" 
                                    Command="{Binding Source={StaticResource Locator}, Path=UpdateDevices.ShowHideEntitledContentsCommand}">
                                <StackPanel>
                                    <Image Source="../Assets/Buttons/plus-button.png" Width="30" Height="30"/>
                                </StackPanel>
                            </Button>
                            <TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding Model.Name}" FontSize="20"/>
                            <Image Grid.Column="2" Grid.Row="0" Height="45" Width="45" Source="../Assets/Buttons/handheld.png"/>
                            <TextBlock Grid.Column="3" Grid.Row="0" Grid.ColumnSpan="3" Text="{Binding Model.AvailableMemoryStorage}"/>
                            <Button Grid.Column="3" Grid.Row="2" Content="Manage Memory" IsEnabled="True" 
                                    Command="{Binding Source={StaticResource Locator}, Path=UpdateDevice.ManageMemoryCommand}" />
                      </Grid>
                        <!--DataGrid for Allowed Contents-->
                        <StackPanel Visibility="{Binding AllowedContentVisibility}">
                            <TextBlock Text="Available Updates" FontWeight="Bold"/>
                            <DataGrid ItemsSource="{Binding Model.AllowedContents}" 
                                      AlternatingRowBackground="LightBlue"
                                      AutoGenerateColumns="False"
                                      CanUserAddRows="False">
                                <DataGrid.Columns>
                                    ...
                                </DataGrid.Columns>
                            </DataGrid>
                        </StackPanel>
                    </StackPanel>
                </Label>
            </Border>
        </DataTemplate>
<ScrollViewer VerticalScrollBarVisibility="Auto">
        <StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
            <Grid x:Name="LayoutRoot">
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <ListBox ItemsSource="{Binding Devices}" 
                     ItemTemplate="{StaticResource ListBoxDataTemplate}"
                     SelectedItem="{Binding SelectedDevice, Mode=TwoWay}"
                     Width="Auto" 
                     HorizontalContentAlignment="Stretch" 
                     SelectionMode="Single"/>
            </Grid>
        </StackPanel>
    </ScrollViewer>
Also, when should I use Binding to a Command:
<Button Command={Binding SomeCommand}....
vs.

Binding using Event
<Button>
   <I:EventName="MouseLeftButtonDown">
        <Command={Binding .... } CommandParameter={Binding....}
...
</Button
Thanks in advance! I've been stuck with this for 2 days now...
Jul 10, 2014 at 8:58 AM
Edited Jul 10, 2014 at 9:03 AM
Here is an example of using commands in a data template for a listbox. hope it helps.
            <ListBox Name="listbox_customer"
                                Grid.Row="0" 
                                Margin="0" 
                                ScrollViewer.CanContentScroll="True" 
                                ItemsSource="{Binding Customers}" 
                                Grid.ColumnSpan="4" 
                                SelectionMode="Single">

                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <Image Source="{Binding Path=MessageInd,Converter={StaticResource ImagePathConverter}}" 
                                                    Width="16" 
                                                    Height="16" 
                                                    Margin="0,0,7,0" />
                                <TextBlock Text="{Binding Path=Message}" 
                                            FontSize="14" 
                                            Margin="0,0,7,0"
                                            FontWeight="Bold" />

                                <Image Source="{Binding Path=Navigation.CustomerIndicator,Converter={StaticResource ImagePathConverter}}" 
                                                    Width="16" 
                                                    Height="16" 
                                                    Margin="0,0,7,0">
                                </Image>
                                <TextBlock>
                                    <Hyperlink NavigateUri="{Binding Path=Navigation.Customer}" Tag="{Binding Path=Navigation.CustomerID}">
                                        <TextBlock Text="{Binding Path=Navigation.CustomerKindDesc}" />
                                        <i:Interaction.Triggers>
                                            <i:EventTrigger EventName="Click">
                                                    <mvvm:EventToCommand Command="{Binding ElementName=listbox_customer, Mode=TwoWay, Path=DataContext.commandSelectItem}" 
                                                                            CommandParameter="{Binding}" />
                                            </i:EventTrigger>
                                        </i:Interaction.Triggers>
                                    </Hyperlink>    
                                </TextBlock>
                            </StackPanel>


                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <mvvm:EventToCommand Command="{Binding ElementName=listbox_customer, Mode=TwoWay, Path=DataContext.commandSelectCustomer}" 
                                                CommandParameter="{Binding SelectedItem, ElementName=listbox_customer}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </ListBox>
You can then get your selected item in the viewmodel
this.commandSelectItem = new RelayCommand<object>((s) => 
                {
                    if (s != null)
                    {
                        GetCustomerHistory((Customer)s);
                    }
                }
            );