How to calculate which item of panel was selected - c#

I'm programing a little C# program for browsing pictures, but I got stuck.
I have a Panel full of PictureBoxes, is there any way to calculate number of the PictureBoxes that were clicked on? For example, if I have a ListBox I can easily type listBox1.SelectedIndex and get the number.
I assume that it's not that easy with Panel, but is there actually any way to do this?

It depends on what you actually want to do. There is no built-in property of PictureBoxes that make or mark them selected.
You can get the index of the PictureBox in the Panel's Controls collection in its Click event like this:
private void pictureBox_Click(object sender, EventArgs e)
{
int index = yourPanel.Controls.IndexOf(sender as PictureBox );
}
You can and probably should assign the same event to all PBs' Clicks!
If you simply want to work with the PictureBox write
PictureBox pb = sender as PictureBox;
pb.Image = ...
Or you could loop over the Controls to find one with Focus. But even if it was there that would only be the keyboard focus, and, as there can only be one, this would not persist even a single Button click.. So this is not recommended.
So if you want to refer to the last clicked PB simply store it in a class variable or maybe in the Panel's Tag:
PictureBox selectedPB = null;
private void pictureBox_Click(object sender, EventArgs e)
{
selectedPB = sender as PictureBox;
// or
yourPanel.Tag = sender as PictureBox;
}
If you want to collect several PBs you can do so by adding them to a List:
List<PictureBox> clickedBoxes = new List<PictureBox>();
private void pictureBox_Click(object sender, EventArgs e)
{
PictureBox pb = sender as PictureBox;
if (!clickedBoxes.Contains(pb) ) clickedBoxes.Add(pb);
}
and access the number as the clickedBoxes.Count ..

Try using the 'SelectedItem' property of your ListBox and bind it to a property on the ViewModel.
If you are using just something like StackPanel? Then no, StackPanel does not have this functionality built in. Use a ListBox with a custom Template.

Related

Multiple OnClick events in c#

I want to ask if i have multiple labels with same function Onclick but with different parameters. How i can handle them without make 30 methods.
I want to make A-Z Filter in windows forms application with C#. I have label for each character (A,B,C,D....,Z). Also i have TreeView with data from DB.
private void labelLetter1_Click(object sender, EventArgs e)
{
//this.labelLetter1.Text
// get value of the label and refresh treeview
}
I want to make this on every characters but without repeat same code.
subscribe an example event to other ones. try like this:
private void labelLetter1_Click(object sender, EventArgs e)
{
Label lbl = (Label) sender;
var text = lbl.Text;
//this.labelLetter1.Text
// get value of the label and refresh treeview
}
now set this event to other labels from Properties window.
The sender parameter is going to be the original object that triggered the event. In your case, it is going to be a Label. This means you could cast the object to a Label.
Additionally you could make a single label_click method and have all labels user that single method.
For example:
private void label_Click(object sender, EventArgs e)
{
String labelText = (sender as Label).Text;
//Your process
}

DragOver button not firing event c#

As the title suggests i am having trouble getting a DragOver event to function correctly. I have over 100 buttons on a form and i want their colour to change when a picturebox is dragged over them. I have set all buttons AllowDrop = true and have included the code below in the method.
private void ShipOver(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.None;
Button b = (Button)sender;
b.BackColor = Color.Green;
label22.Text = "";
}
I do not see why this will not work. I also have a DragLeave method which simply changes the colour to a different one.
One thing to note is that the item i am dragging over the button is larger than the button itself. Not sure whether this will have an effect.
You need to wire up the events to your method. If all of the buttons are in a single panel, you can do something like this in your form's constructor:
foreach (Button b in panel1.Controls.OfType<Button>()) {
b.DragOver += ShipOver;
}
Same principle applies to the DragLeave event.

How to get the item right clicked on from ContextMenuStrip?

I have a PictureBox.
If I right click the PictureBox, my ContextMenuStrip (right click menu) appears.
In that ContextMenuStrip is a ToolStripMenuItem (one of the options in the right click menu).
There is an event on the ToolStripMenuItem that handles what happens if that option is clicked.
We're starting from ToolStripMenuItem's "Clicked" function. I need to somehow get back to the PictureBox programmatically. From there, I can modify the PictureBox.
ToolStripMenuItem -> ContextMenuStrip -> PictureBox
How would I go about this?
If the click event handler for your menu item is named OnToolStripMenuItemClick, the following might be an approach to your problem:
private void OnToolStripMenuItemClick(object sender, EventArgs e)
{
var menuItem = sender as ToolStripMenuItem;
var contextMenu = menuItem.Parent as ContextMenuStrip;
var pictureBox = contextMenu.SourceControl;
}
Of course, don't forget to check for null when accessing properties after conversion with as.
I'm not sure that I really understood your problem, but I guess you want to let users can return to the picturebox when they want to cancel current operation by clicking the right button. In this case, you should not implement your work in click event, because right and left button both can trigger the click event, instead, you should process your work in the event "MouseUp", like this:
private void menuItemBack_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
MessageBox.Show("back item is clicked");
}
else
{
MessageBox.Show("I will come back.");
//do your return things here.
}
}
I've just come across this same problem in C#, and the path to the value seems to be something like:
sender.Owner.SourceControl;
However, since sender, Owner and so on are generic classes, I had to cast everything as follows:
PictureBox pb = (PictureBox) ((ContextMenuStrip)((ToolStripMenuItem)sender).Owner).SourceControl;
Ugly, but it works.

change cursor over a pictureBox

i was trying to implemet an image button in winforms application as i can ...easy when using asp.net
the problem seem to be(i suspect) that when the mouse is over the image inside the picturebox
it is not responding or not triggering the mouseEnter event
it looks like if i had a picture that is smaller than the pictureBox Size it will accept the reason to trigger the event but over the image within the pictureBox it would Not ?
the trick was to set pictureBox to sizeMode=zoom. then do 2 things when the mouse is over the "imageButton" : change the size of PictureBox a little larger + change cursor to hand
so i will get a kind of mouse over effect as i could with asp.net
did anyone have that problem ?
at first i tried mouseHover, then i thought enter would do better as it only requiers the mouse to pass the borders of the picture box... both enter and hover events did not work for me ...
Edit :
the event does trigger , i can see that if i initially set sizemode to CenterImage and inside the event
i ask for sizemode=zoom, so the effect dose occur ..but cursor.current=Cursors.Hand will not change.
This should work
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Cursor = Cursors.Hand;
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
pictureBox1.Cursor = Cursors.Default;
}
seem like i should have known better how to use Cursors class .
cursor=Cursors.hand;
rather than
cursor.current=Cursors.hand;
that was embarrassing ..
only add MouseMove event on pictureBox and set a Cursor for this
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
pictureBox1.Cursor = Cursors.Hand;
}

How do I associate a button with a control?

OR - How To Shave A Koala To Stop It Looking Squashed. (But I didn't think that would make a suitably techy title)
The Problem: You have three preview images derived from a main image. The preview images are resized for standardised picture spaces on a company website, the main image can be any size image from anywhere.
Example: The main image is a hi-res image of a koala bear measuring 2000x2250. Your previews want to render the koala at 200x200, 200x50 and 250x150.
Your utility program resizes and stretches the original image to the size of your three "actual size" previews but obviously each preview looks a bit squashy and you know everyone hates to see a squashed koala.
To resolve this you add a little cropping method to your program which shaves five pixels from the preview on the desired side. This means you should be able to resize your image and unsquash your koala by shaving off the unnecessary parts of the image.
You add four buttons to each preview image picture box and create four generic methods for sending the correct shaving instructions to the crop method. You want to associate each specific button with a specific picturebox on the form, but you want to send all the click events to four generic functions.
How do you tell the generic function which of the three preview picturebox images you want it to shave in an elegant and wonderful way?
Example Code:
//cropPict=method for cropping the picture in the relevant picturebox.
//CropSide=a little enum which tells the method which side to crop.
private void btnT_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Top);
}
private void btnB_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Bottom);
}
private void btnR_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Right);
}
private void btnL_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Left);
}
EDIT: As it happens, inspired by Hans below, rather than just stuffing the PictureBox into the tag. Which was a great idea I actually put a KeyValuePair into the tag for each button like so:
btnCCB.Tag = new KeyValuePair<CropSide,PictureBox>(CropSide.Bottom,pbxKoala);
btnCCL.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Left, pbxKoala);
btnCCR.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Right, pbxKoala);
btnCCT.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Top, pbxKoala);
Then I could just wire all the buttons up to a single event handler like so:
private void btnC_Click(object sender, EventArgs e)
{
Button btnSend = (Button)sender;
KeyValuePair<CropSide, PictureBox> kvCrop = (KeyValuePair<CropSide, PictureBox>)btnSend.Tag;
cropPict(kvCrop.Value,kvCrop.Key);
}
Of course, there's still plenty more to do but that pretty much sorted out my problem. Thanks Hans!
Use the Button.Tag property to store a reference to its associated PictureBox. Cast sender to Button:
public Form1()
{
InitializeComponent();
button1.Tag = pictureBox1;
button1.Click += btnT_Click;
// etc..
}
private void btnT_Click(object sender, EventArgs e)
{
var btn = (Button)sender;
cropPict((PictureBox)btn.Tag, CropSide.Top);
}

Categories