3

I'm new to using WPF forms, I have created a page that displays images from a database, but despite days of searching I cannot find a way of knowing which image has had a mouse over or mouse click event on it.

To setup the images I have:

public class RBimageData
    {
        private string _Title;
        public string Title
        {
            get { return this._Title; }
            set { this._Title = value; }
        }

        private BitmapImage _ImageData;
        public BitmapImage ImageData
        {
            get { return this._ImageData; }
            set { this._ImageData = value; }
        }

        private String _ImageID;
        public String ImageID
        {
            get { return this._ImageID; }
            set { this._ImageID = value; }
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        RBpartsList rbPartsList = mongoDB.GetRBparts("elements", 1, 7); // get parts from database

        List<RBpartsImages> rbImages = rbPartsList.RBparts;

        List<RBimageData> md = new List<RBimageData>();           
        foreach (RBpartsImages img in rbImages)
        {
            RBimageData m = new RBimageData
            {
                Title = img.ImageFilename,
                ImageID = "id_"+img.PartNum,
                ImageData = LoadImage(rbPartsList.FilePath,img.ImageFilename) }; // provides BitmapImage URI for image                
                md.Add(m);
        }

        RBbox.ItemsSource = md.ToArray();

} and the images are displayed in the XAML, I have used the Tag element to hold the ImageID:

   <ListView x:Name="RBbox" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="143" Margin="10,0,10,10" Background="#FFE6E2E2">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <UniformGrid Columns="7" Rows="1" HorizontalAlignment="Stretch"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Vertical" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">

                                <Border BorderThickness="1" BorderBrush="#FF000000" VerticalAlignment="Top" HorizontalAlignment="Left" Width="100" Height="100" Background="#FFC1A0A0">

                                    <Button 
                                           MouseEnter="IdentifyPartImage_MouseEnter" 
                                           MouseLeave="IdentifyPartImage_MouseLeave" >
                                        <Image Source="{Binding ImageData}" 
                                               HorizontalAlignment="Stretch" VerticalAlignment="Top" 
                                               Stretch="UniformToFill" 
                                               Tag="{Binding ImageID}"/>
                                    </Button>
                                </Border>
                                <TextBlock Text="{Binding Title}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="100" Height="14" FontSize="10" />

                            </StackPanel>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>

but in my codebehind the this.Tag is always null:

        private void IdentifyPartImage_MouseEnter(object sender, MouseEventArgs e)
    {
        // this fails - tag is null
        var imgId = this.Tag.ToString();              
        Debug.WriteLine("id: {0}, {1}", "imageID", imgId.ToString());
    }

It won't work with x:Name="{Binding ImageID}".. I can't find anything that will let me identify which image has been clicked, can you help?

Thanks.

kazzle101
  • 67
  • 3
  • As a note, you can directly assign `RBbox.ItemsSource = md;`. ToArray is redundant. – Clemens Jun 02 '18 at 09:16
  • Possible duplicate of [WPF Image Command Binding](https://stackoverflow.com/questions/3885007/wpf-image-command-binding) – ASh Jun 02 '18 at 17:38

1 Answers1

1

When you reference this in your code-behind, it points to the Window object. You are looking for the Tag property of the Image control.

For that I recommend defining the MouseEnter="IdentifyPartImage_MouseEnter" and MouseLeave="IdentifyPartImage_MouseLeave" events on the Image control, and then the sender parameter will be that Image object.

In your XAML:

<Button>
    <Image Source="{Binding ImageData}"
           HorizontalAlignment="Stretch"
           VerticalAlignment="Top"
           Stretch="UniformToFill"
           Tag="{Binding ImageID}"
           MouseEnter="IdentifyPartImage_MouseEnter"
           MouseLeave="IdentifyPartImage_MouseLeave"/>
 </Button>

And in your code-behind:

private void IdentifyPartImage_MouseEnter(object sender, MouseEventArgs e)
{
    var imgId = ((Image)sender).Tag.ToString();              
    Debug.WriteLine("id: {0}, {1}", "imageID", imgId);
}
Clemens
  • 123,504
  • 12
  • 155
  • 268
oriash
  • 149
  • 5
  • Thanks for that, a really simple solution too. How did you know that? – kazzle101 Jun 02 '18 at 09:01
  • 1
    The sender of an event is always the element where the event handler is attached. As a note, you do not actually need to use the Image's Tag at all. You can as well leave the mouse event handlers at the Button, and access the Button's (the sender then) DataContext. It will hold a reference to the corresponding item object, so you can access its ID by `((RBImageData)((Button)sender).DataContext).ImageID` – Clemens Jun 02 '18 at 09:14