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?
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);
}