I have a method which run on a click of a button.
The methods goes to a database and return all products ids(list) wihich match
a specific keyword.
It then uses that id to get the corresponding image from the database
and adds it to a picturebox.
The problem I have is with adding the click evethandler to each picturebox. If I click the search button a second time there is now two eventhndler registered to that picturebox and so on. So when I click on a picurebox sfter pressing the search button twice i will het two messagebox.
Is there a way to drop the previous and only keep the latest eventhandler?
private void btnSearch_Click(object sender, EventArgs e)
{
ClearPicBoxs();
if((!txtBoxSearch.Text.Equals("Search...") || !txtBoxSearch.Text.Equals("")) && isLoggedIn)
{
//Get Product ids from database which have supplied keyword
DAOKeyword.SelectKeywords(txtBoxSearch.Text, productIdsList);
int cnt = 0;
foreach (int productId in productIdsList)
{
ImageDAOImpl DAOIamge = new ImageDAOImpl();
picPrd = pictureBoxList[cnt];
picPrd.Text = productId.ToString();
picPrd.Click += new System.EventHandler((sender1, e1) => picPrd_Click(sender, e, productId));
picPrd.Image = ByteArrayToImagebyMemoryStream(DAOIamge.SelectImage(productId));
picPrd.SizeMode = PictureBoxSizeMode.StretchImage;
picPrd.Refresh();
cnt++;
}
lblLatest_Search.Text = "''" + txtBoxSearch.Text + "''";
productIdsList.Clear();
}
else
{
//Select Latest Posted Products
}
}
private void picPrd_Click(object sender, EventArgs e, int productId)
{
//Use productId to get info about product
MessageBox.Show(productId.ToString());
}
I am not sure where is the list pictureBoxList is populated, and why you need to assign its items to your controls as long as you set control properties manually.
If you re-instantiate the control each time before assigning the event handler, it should fire it only once
My suggestion is to replace the below line
picPrd = pictureBoxList[cnt];
With the below line
picPrd = new PictureBox();
Related
I am trying to fill two text box in a form using button controls but it seems to work for 1 only. when I run the program, I can't select between two text box. what condition should I use?
private void Button0_Click(object sender, EventArgs e)
{
if (???????????????????)
{
metroTextBoxQuantity.Text = metroTextBoxQuantity.Text + "0";
}
else
{
metroTextBoxItemcode.Text = metroTextBoxItemcode.Text + "0";
}
}
One possible solution is to create a Control variable that stores a reference to the last clicked textbox. This would be handled by the Click event for both textboxes. Then, in your number button clicks, just append the number to the selected textbox variable. Something like this:
Control SelectedTextbox { get; set; } = null;
//Use this event handler for both the Quantity and Itemcode textbox
public TextBox_Click(object sender, EventArgs e)
{
SelectedTextbox = (Control)sender;
}
private void Button0_Click(object sender, EventArgs e)
{
if(SelectedTextbox == null)
throw new Exception("SelectedTextbox has not been set");
SelectedTextbox.Text += "0";
}
Note, if MetroTextBox doesn't inherit from Control, you'll need to change SelectedTextbox to a different type. It most likely does though.
You also may want to consider using a single event handler for all the button clicks instead of one for each. You can either parse what number button was clicked using the sender's name, or you can store the number of the button in the button's Tag and read it from there. But that's best left for another question.
I have an aspx page. On pageLoad a call a method that loads a user control
protected void Page_Load(object sender, EventArgs e)
{
LoadUC();
}
This loads the user control onto the page (into a placeholder) passing a few generic values.
private void LoadUC()
{
ucTS ctrl = (ucTS)Page.LoadControl(_ucTSPath);
ctrl.ParentId = 0;
ctrl.addNew = false;
phFG.Controls.Add(ctrl);
}
The user control (which contains a repeater) loads the initial placeholder as well as another placeholder on the initial page:
protected void Page_Load(object sender, EventArgs e)
{
LoadItems();
}
private void LoadBOMItems()
{
List<Item> dtItem;
if (ParentId == 0)
{
if (ViewState["ItemFG"] == null)
{
dtItem = //Gets list of items
}
else
{
dtItem = (List<Item>)ViewState["ItemFG"];
}
ViewState["ItemFG"] = dtItem;
}
else
{
if (ViewState["Items" + ParentId] == null)
{
dtItem = //get list of items
}
else
{
dtItem = (List<Item>)ViewState["Items" + ParentId];
}
ViewState["Items" + ParentId] = dtItem;
}
if (dtItem.Count > 0)
rptTSItem.DataSource = dtItem;
rptTSItem.DataBind();
}
}
in the binding, I bind the repeater, but I am also adding more of the same user control.
The problem comes when I click add a new item to the repeater. The initial click, everything saves fine and a new row is added. The second click the user control is not found on the initial page and so the save method is not fires. The 3rd click, everything is fine, the 4th, the user control is not found. This keeps happening. Why is my usercontrol not always found? I have tried doing a postback check in multiple places, but that doesn't seem to work.
I am still not 100% sure why the event would fire properly every OTHER time as opposed to just the first time, but the solution was simply adding an ID to the user control.
private void LoadUC()
{
ucTS ctrl = (ucTS)Page.LoadControl(_ucTSPath);
ctrl.ParentId = 0;
ctrl.addNew = false;
ctrl.ID = "someID"
phFG.Controls.Add(ctrl);
}
and whenever I re-added the user control from within the user control, I pass the same ID.
Here is my question:
Im making a booking cinema system in c#, windows form
Let's say i have 5 columns of 5 rows of pictureboxes that on form load get their value, avaliable or not from the database.
The user then click on the seat he wants (and the image of the pictuebox change) and press a submit button.
How i can check the image of every picturebox (to determine if he want this seat or not) together?
I can do something like this
if (picturebox11.image=="seatchecked"){seats[]+=11;}
if (picturebox12...
But im wondering if there is another faster way to do it. (the position of the pictureboxes is fixed if that helps)
I have done this so far:
private void button1_Click(object sender, EventArgs e)
{
List<PictureBox> pb = new List<PictureBox>();
pb.Add(seat11);
pb.Add(seat12);
pb.Add(seat13);
pb.Add(seat14);
pb.Add(seat15);
pb.Add(seat21);
pb.Add(seat22);
pb.Add(seat23);
pb.Add(seat24);
pb.Add(seat25);
pb.Add(seat31);
pb.Add(seat32);
pb.Add(seat33);
pb.Add(seat34);
pb.Add(seat35);
for (int i = 0; i < 20; i++) {
pb[i].Click += pictureBox_Click;
}
}
void pictureBox_Click(object sender, EventArgs e)
{
this.pictureBox.Image = ArgyroCinema.Properties.Resources.seatred;
}
Store each PictureBox in a list and iterate through them. Also, when the user selects/deselects a seat, change the Tag property of the PictureBox as, at the moment, you're trying to compare a string to an Image (picturebox11.Image returns an Image object).
List<PictureBox> pb = new List<PictureBox>();
pb.Add(pictureBox1);
pb.Add(pictureBox2);
//etc..
Alternatively, you can use the methods suggested here to get all PictureBox objects in your form to save you having to type it out above.
Then just iterate through them and read their Tag property. In this case I've used true to represent that they want the seat but Tag is an object type, so you can use whatever type you like.
foreach(PictureBox p in allPictureBoxes)
{
if((bool)p.Tag == true)
{
//seat wanted
}
else
{
//seat not wanted
}
}
Update from comments
void pictureBox_Click(object sender, EventArgs e)
{
PictureBox pb = sender as PictureBox;
if(pb != null)
pb.Image = ArgyroCinema.Properties.Resources.seatred;
}
For a school project, I have to make a table reservation system,
I made the following (just a small part).
PictureBox[] pb = new PictureBox[70] { pictureBox1, pictureBox2, pictureBox3,etc.. };
foreach (PictureBox p in pb)
{
p.BorderStyle = BorderStyle.Fixed3D;
p.BackColor = Color.White;
p.MouseEnter += new EventHandler(mouseOn);
p.MouseClick += new MouseEventHandler(mouseClick);
}
private void mouseOn(object sender, EventArgs e)
{
((PictureBox)sender).BackColor = Color.Green;
}
private void mouseClick(object sender, EventArgs e)
{
reservationForm rf = new reservationForm();
rf.ShowDialog();
}
I chose for pictureboxes to represent the tables, the default BackColor is white, and when the mouse enters the BackColor turns green.
When you click on 1 of those PictureBoxes my reservationForm will open, this is where you can further fill in the details to book the table.
but the part where I get stuck now is that I don't know on my reservation form which PictureBox I clicked, so I need to get something like the index of the PictureBox array.
How do I fix this?
You know how to do it! :)
You're already doing it correctly on the mouseOn event handler. Just do the same cast of the sender parameter.
private void mouseClick(object sender, EventArgs e)
{
PictureBox clickedBox = (PictureBox)sender;
reservationForm rf = new reservationForm();
rf.ShowDialog();
}
If you need the index, you can use Array.IndexOf, assuming your pb array is a class level variable and not a method local.
int index = Array.IndexOf(pb, clickedBox);
Check sender
private void mouseClick(object sender, EventArgs e)
{
PicterBox pb = (PicterBox)sender;
...
}
In your "MouseOn" you already use (PictureBox)sender to get a reference to the picturebox.
Then you can walk through the array to compare the picturebox at a specific index to the clicked one. When you have a match, you found the index.
var clicked = (PictureBox)sender;
int index = 0;
while (index < pb.Length && pb[index] != clicked) index = index+1;
// now index is either 70 (if not found) or the position you want (0..69)
Maybe you can set in for cycle a name at each picturebox equals at the corrispondent index. So in the listener u can use
PicterBox pb = (PicterBox)sender;
and get the name that is the index.
You have many options. I will suggest some of them:
Create a public class variable or property and store the current selected Picturebox on the click event, so you can access it from the form;
Pass in the Picturebox for the constructor of the form (creating a constructor that accepts this info and stores it in an internal variable).
Is there any possibility to get a value of doubleclicked row in ListView?
I registered an event:
private void lvLista_DoubleClick(object sender, EventArgs e)
{
MessageBox.Show(lvLista.SelectedItems.ToString());
}
But on message, when i doubleclick some row in listview i get:
System.Windows.Forms.ListView+SelectedListViewItemCollection
What is more, I have got 2 columns in listview:
lvLista.Columns.Add("ID");
lvLista.Columns.Add("Tilte");
And i want to show in messagebox the "ID" of doubleclicked row.
How to do it? How to get a values from this event?
If you handle the MouseDown and/or MouseDoubleClick events of the ListView control, and use the HitTest method to determine the target of the mouse action, you will know which item has been double clicked. This is also a good means to determine if NO item was clicked (for example, clicking on the empty area in a partially filled list.
The following code will display the clicked item in a textbox if a single click occurs, and will pop up a message box with the name of the double-clicked item if a double click occurs.
If the click or double click occur in an area of the list view not populated by an item, the text box or message box inform yopu of that fact.
This is a trivial example, and depending on your needs, you will have to mess with it a little.
UPDATE: I added some code which clears the SelectedItems property of the Listview control when an empty area of the list is clicked or double-clicked.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
listView1.MouseDown += new MouseEventHandler(listView1_MouseDown);
listView1.MouseDoubleClick += new MouseEventHandler(listView1_MouseDoubleClick);
this.Load += new EventHandler(Form1_Load);
}
void Form1_Load(object sender, EventArgs e)
{
this.SetupListview();
}
private void SetupListview()
{
ListView lv = this.listView1;
lv.View = View.List;
lv.Items.Add("John Lennon");
lv.Items.Add("Paul McCartney");
lv.Items.Add("George Harrison");
lv.Items.Add("Richard Starkey");
}
void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
ListViewHitTestInfo info = listView1.HitTest(e.X, e.Y);
ListViewItem item = info.Item;
if (item != null)
{
MessageBox.Show("The selected Item Name is: " + item.Text);
}
else
{
this.listView1.SelectedItems.Clear();
MessageBox.Show("No Item is selected");
}
}
void listView1_MouseDown(object sender, MouseEventArgs e)
{
ListViewHitTestInfo info = listView1.HitTest(e.X, e.Y);
ListViewItem item = info.Item;
if (item != null)
{
this.textBox1.Text = item.Text;
}
else
{
this.listView1.SelectedItems.Clear();
this.textBox1.Text = "No Item is Selected";
}
}
}
Try this:
private void lvLista_DoubleClick(object sender, EventArgs e)
{
MessageBox.Show(lvLista.SelectedItems[0].SubItems[0].Text);
}
I know this thread is old but nobody here answered the question properly in my opinion. For those in the future, try this, from MSDN:
// User must double-click to activate item
myListView.Activation = System.Windows.Forms.ItemActivation.Standard;
// Add event handler
myListView.ItemActivate += new
System.EventHandler(this.myListView_ItemClick);
Since the accepted answer didn't help me i thought that I would share my solution to the same problem: getting data from a specific column in a listview in the double click event.
The following line returns the data of the second column in the row that I've double clicked on as a string:
private void listViewOutput_DoubleClick(object sender, EventArgs e)
{
string content = listViewOutput.Items[listViewOutput.SelectedIndices[0]].SubItems[1].Text
}
Thanks; this is what I needed. I thought I'd also mention one could set up the local info variable more generally as:
ListViewHitTestInfo info = ((ListView)sender).HitTest(e.X, e.Y);
Try this
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
ListViewHitTestInfo hit = listView1.HitTest(e.Location);
Rectangle rowBounds = hit.SubItem.Bounds;
Rectangle labelBounds = hit.Item.GetBounds(ItemBoundsPortion.Label);
int leftMargin = labelBounds.Left - 1;
string x = hit.Item.Text;
}