Search code examples
silverlightxamlcontextmenuwindows-phone-8silverlight-toolkit

How to make context menu work for windows phone?


I am using ContextMenu from Windows Phone Control toolkit. Wondering how do I know which list item in the list is pressed? It seems I can know which context menu is selected but I have no way to know which list item is operated on. Please help. Thanks!

        <DataTemplate x:Key="ListItemTemplate">
            <StackPanel Grid.Column="1" VerticalAlignment="Top">
                <TextBlock Tag="{Binding Index}"  Text="{Binding SName}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" />
              <toolkit:ContextMenuService.ContextMenu>
                <toolkit:ContextMenu>
                  <toolkit:MenuItem Header="Add to playlist" Click="Move_Click"/>
                </toolkit:ContextMenu>
              </toolkit:ContextMenuService.ContextMenu>
            </StackPanel>

        private void Move_Click(object sender, RoutedEventArgs e)
    {
        String name = (string)((MenuItem)sender).Header;
        // how to know which index of the item is targeted on
    }

Solution

  • I would also recommend MVVM, but it can be simplified. No need to go to the extreme of having a ViewModel for every object. The key is to bind the command to the DataContext of your ItemsControl (eg ListBox).

    Let's assume that your ItemTemplate is for a ListBox, the ListBox has it's ItemsSource property bound to your ViewModel. Your xaml would look like this:

    <ListBox x:Name="SongsListBox" ItemsSource="{Binding Songs}">
        <ListBox.ItemTemplate>
            <DataTemplate >
                <StackPanel >
                    <TextBlock Text="{Binding SName}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" />
                    <toolkit:ContextMenuService.ContextMenu>
                       <toolkit:ContextMenu>
                           <toolkit:MenuItem Header="Add to playlist" Command="{Binding DataContext.AddToPlaylistCommand, ElementName=SongsListBox}" CommandParameter="{Binding}"/>
                       </toolkit:ContextMenu>
                    </toolkit:ContextMenuService.ContextMenu>
                </StackPanel>              
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    Your ViewModel, would then have the property Songs, that is a collection of your model object. It also has an ICommand AddToPlaylistCommand. As I've said before, my favorite implementation of ICommand is the DelegateCommand from the PNP team.

    public class ViewModel : INotifyPropertyChanged
    {
        public ViewModel()
        {
            Songs = new ObservableCollection<Songs>();
            AddToPlaylistCommand = new DelegateCommand<Song>(AddToPlaylist);
        }
        public ICollection<Songs> Songs { get; set; }
        public ICommand AddToPlaylistCommand  { get; private set; }
    
        private void AddToPlaylist(Song song)
        {
            // I have full access to my model!
            // add the item to the playlist
        }
    
        // Other stuff for INotifyPropertyChanged
    }