wpfcontextmenustackpanel

Get Selected Item from Context Menu


I am creating a set of images dynamically and putting them into a Stack Panel like this :-

            Image image = new Image();
            image.Name = "image_" + iCounter;
            image.Height = 100;
            image.Width = 100;
            image.Source = bitmap;
            image.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
            image.Stretch = Stretch.Fill;
            image.VerticalAlignment = VerticalAlignment.Top;
            //image.MouseDown += new MouseButtonEventHandler(image_MouseDown);
            image.ToolTip = "Right-Click for Options";
            image.ContextMenu = GetContextMenu();

            Separator separator = new Separator();
            separator.Name = "separator_" + iCounter;

            AddImagesStackPanel.Children.Add(image);
            AddImagesStackPanel.Children.Add(separator);

            iCounter++;

Then in the Context Menu I have this code :-

    private System.Windows.Controls.ContextMenu GetContextMenu()
    {
        System.Windows.Controls.MenuItem mi1;
        System.Windows.Controls.MenuItem mi2;
    
        System.Windows.Controls.ContextMenu _contextMenu = new System.Windows.Controls.ContextMenu();
    
        mi1 = new System.Windows.Controls.MenuItem();
        mi1.Header = "Show Normal Size";
        mi1.Click += new RoutedEventHandler(ContextMenuItem1_Click);

        mi2 = new System.Windows.Controls.MenuItem();
        mi2.Header = "Remove image";
        mi2.Click += new RoutedEventHandler(ContextMenuItem2_Click);

        _contextMenu.Items.Add(mi1);
        _contextMenu.Items.Add(mi2);
        return _contextMenu;
    }

Now I wish to get the selected item when the user right clicks on an image and I have this code :-

    private void ContextMenuItem2_Click(object sender, RoutedEventArgs e)
    {
        object obj = e.OriginalSource;

        string imageName = ((System.Windows.Controls.Image)obj).Name;
        string[] split = imageName.Split('_');
        imageUploads.RemoveAt(Convert.ToInt32(split[1]));
        DisplayImagesInStackPanel(imageUploads);
    }

But obj does not contain the name of the image since its a RoutedEventArgs. Is there any way I can get the selected item in the context menu?


Solution

  • After discussing this in the comments this should work:

    // The binding source.
    private readonly ObservableCollection<BitmapImage> _imageList = new ObservableCollection<BitmapImage>();
    public ObservableCollection<BitmapImage> ImageList
    {
        get { return _imageList; }
    }
    

    How to display this and set up the ContextMenu:

    <ItemsControl ItemsSource="{Binding ImageList}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <Image Source="{Binding}" Width="100" Height="100"
                           HorizontalAlignment="Left" Stretch="Fill"
                           VerticalAlignment="Top" ToolTip="Right-Click for Options">
                        <Image.ContextMenu>
                            <ContextMenu>
                                <MenuItem Header="Show Normal Size" Click="Image_CM_ShowNormalSize_Click"
                                          Tag="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget}"/> <!-- The placement target is the object to which the context menu belongs, i.e. the image -->
                                <MenuItem Header="Remove Image" Click="Image_CM_RemoveImage_Click"
                                          Tag="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.DataContext}"/> <!-- The DataContext of the Image is the BitmapImage, which should be removed from the list -->
                            </ContextMenu>
                        </Image.ContextMenu>
                    </Image>
                    <Separator/>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    What the handlers might look like:

    private void Image_CM_ShowNormalSize_Click(object sender, RoutedEventArgs e)
    {
        Image img = (sender as FrameworkElement).Tag as Image;
        img.Width = (img.Source as BitmapImage).PixelWidth;
        img.Height = (img.Source as BitmapImage).PixelHeight;
    }
    
    private void Image_CM_RemoveImage_Click(object sender, RoutedEventArgs e)
    {
        BitmapImage img = (sender as FrameworkElement).Tag as BitmapImage;
        // If the image is removed from the bound list the respective visual elements
        // will automatically be removed as well.
        ImageList.Remove(img);
    }