Right click menu then item pointing to a class - c#

I want to be able to right click on an image and for there to be a menu show up. When I then click on one of the items I want it to point to a class:
private void link1add_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("Add", HandleContextMenuAdd);
cm.MenuItems.Add("Remove", HandleContextMenuRemove);
link1add.ContextMenu = cm;
}
}
private void HandleContextMenuAdd(object sender, EventArgs e)
{
MessageBox.Show("Adding");
}
private void HandleContextMenuRemove(object sender, EventArgs e)
{
MessageBox.Show("Removing");
}
Code edited since first posted.
Thanks all for your help.

What about a lambda expression?
cm.MenuItems.Add("Item 2", (_, __) => {
if (...) ReadDocument();
});
or
cm.MenuItems.Add("Item 2", (_, __) => { this.myClassInstance.DoSomething(); });
Alternatively, you can create a method with the signature of the expected event handler:
cm.MenuItems.Add("Item 2", HandleContextMenuClick);
private void HandleContextMenuClick(object sender, EventArgs e)
{
if (...) ReadDocument();
}
That method doesn't need to be in the same class (you can write this.myClassInstance.HandleContextMenuclick for example). But I would hide the implementation detail from other classes to avoid unnecessary coupling.

Pattern for your own code after this:
public class ReadDocumentEventArgs : EventArgs
{
public string ImageInfo { get; set; }
}
public void ReadDocument(object sender, ReadDocumentEventArgs ea)
{
// do whatever you need to do
MessageBox.Show(ea.ImageInfo); // example
}
private void link1add_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
PictureBox imageCtrl = sender as PictureBox;
// get the information you need to get from your control to identify it
string imgInfo = "Hello, World!"; // example
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("Item 1");
cm.MenuItems.Add("Item 2",
(EventHandler)((s, rde) =>
{ ReadDocument(s, new ReadDocumentEventArgs()
{ ImageInfo = imgInfo });
}));
link1add.ContextMenu = cm;
}
}
In your MouseDown over your image you can create a menu item using the code I supplied above that will call an event handler called ReadDocument. Notice that there is a ReadDocumentEventArgs class that you can customize to contain the necessary properties that will help you identify which image you have clicked on.
So, in the example I have above one of the first things that happens in MouseDown is that you get the instance of image control (I assume it's a Picture Box, but you can cast it to whatever it really is).
At that point, you can then get a file name or whatever from your image that identifies it from the other controls on your form.
Next, when creating a context menu item, it tells the menu item to call ReadDocument but passes in the special data just taken from the image control.
In the ReadDocument method, you can then do whatever you need to do. In my example, I simply throw up a MessageBox to show you what data you passed in.

What you will want is to put another event handler and call your readdocument method.

Related

C# assign an event to a "group" of controls?

I have a big numbers of labels custom controls let's say 100.
I would like to give them an MouseHover event.
I could do something like:
private void label_custom1_MouseHover(object sender, EventArgs e)
{
TextBox.Text = label_custom1.backcolor.ToString();
}
But then I would need to do that 100 times. Since I have 100 of them.
Is there a way to do that only once?
I guess I should probably declare the function in my custom_label class but so far I couldn't make it work.
Any Idea how to proceed?
Create only one event handler method like this:
private void Label_MouseHover(object sender, EventArgs e)
{
TextBox.Text = (sender as Label).BackColor.ToString();
}
And subscribe all Events to that method:
this.label_custom1.MouseHover += Label_MouseHover;
this.label_custom2.MouseHover += Label_MouseHover;
Thank you, this was very helpful.
This part didnt work though, it couldnt recognize the controls:
private void SetEventAllLabels()
{
var labels = Controls.OfType<Label>().Where(x => x.Name.StartsWith("label"));
foreach (var label in labels)
{
label.MouseHover += Common_MouseHover;
}
}
So I create a list containing all the label names and Then it works using this:
foreach (string i in liste)
{
CustomLabel x = (CustomLabel)(this.Controls.Find(i, true).FirstOrDefault() as Label);
x.MouseEnter += Common_MouseHover;
}
As a side note, using MouseEnter instead of MouseHover makes it much more responsive (faster reaction!)
Firstly, create a common event, we receive the Label posted here.
private void Common_MouseHover(object sender, EventArgs e)
{
TextBox.Text = (sender as Label).BackColor.ToString();
}
Give the common event to all Labels on the form. Here I assume Label names start with label, for example label1, label2, label3 ...
private void SetEventAllLabels()
{
var labels = Controls.OfType<Label>().Where(x => x.Name.StartsWith("label"));
foreach (var label in labels)
{
label.MouseHover += Common_MouseHover;
}
}
Call the SetEventAllLabels () method in the Load method of the form.
private void Form1_Load(object sender, EventArgs e)
{
SetEventAllLabels();
}

Getting a class property value from a textbox

I am wondering how to return the value of a class property with the input of a textbox? i.e. the input in the nameTextBox would go to the Name property of a Pet class, the breedTextBox would be the Breed property, etc.
Using C# windows form.
Pet pet = new Pet();
pet.Name = nameTextBox.Text;
etc.
If your question is how to get this code executed then either have an "update" Button, and in its Click event handler run this code, or subscribe to the Textbox's TextChanged event and do it there. (You can also use binding, a bit more complicated. See here.)
This logic can be accomplished by handling the TextChanged event of your TextBox instances. Given the current Pet instance m_Pet (allocated within your class as a member, for example):
private Pet m_Pet = new Pet();
and the events subscription in the InitializeComponent method of the form:
m_TextBoxName = new TextBox();
m_TextBoxName.TextChanged += TextBoxName_TextChanged;
here is how you can accomplish this:
private void TextBoxName_TextChanged(Object sender, EventArgs e)
{
m_Pet.Name = m_TextBoxName.Text;
}
And the same can be performed for as many properties as you want:
private void TextBoxBreed_TextChanged(Object sender, EventArgs e)
{
m_Pet.Breed = m_TextBoxBreed.Text;
}
private void TextBoxType_TextChanged(Object sender, EventArgs e)
{
m_Pet.Type = m_TextBoxType.Text;
}

Remove control created at runtime

I wrote some code to create an additional textbox during runtime. I'm using the metro framework, but this shouldn't matter for my question.
When you click a button, a textbox is being created by a private on_click event:
private void BtnAddButton_Click(object sender, EventArgs e)
{
MetroFramework.Controls.MetroTextBox Textbox2 = new MetroFramework.Controls.MetroTextBox
{
Location = new System.Drawing.Point(98, lblHandy.Location.Y - 30),
Name = "Textbox2",
Size = new System.Drawing.Size(75, 23),
TabIndex = 1
};
this.Controls.Add(Textbox2);
}
What I want to do now is to use the click event of another button, to remove the Textbox again. What I am not sure about is, if I have to remove just the controll or also the object itself. Furthermore I can neither access the Textbox2 Control nor the object from another place.
private void BtnRemoveTextbox2_Click(object sender, EventArgs e)
{
this.Controls.Remove(Textbox2);
}
This does not work, since the other form does not know about Textbox2. What would be the best way to achieve my goal? Do I have to make anything public and if so, how do I do that?
You have to find it first before you choose to remove it.
private void BtnRemoveTextbox2_Click(object sender, EventArgs e)
{
MetroFramework.Controls.MetroTextBox tbx = this.Controls.Find("Textbox2", true).FirstOrDefault() as MetroFramework.Controls.MetroTextBox;
if (tbx != null)
{
this.Controls.Remove(tbx);
}
}
Here, Textbox2 is the ID of your textbox. Please make sure you're setting the ID of your textbox control before adding it.
You need to find those controls using Controls.Find method and then remove and dispose them:
this.Controls.Find("Textbox2", false).Cast<Control>().ToList()
.ForEach(c =>
{
this.Controls.Remove(c);
c.Dispose();
});
Since the control was created in another form, the current form has no way of knowing it by its instance name.
To remove it, loop through all controls and look for its Name:
private void BtnRemoveTextbox2_Click(object sender, EventArgs e)
{
foreach (Control ctrl in this.Controls)
{
if (ctrl.Name == "Textbox2")
this.Controls.Remove(ctrl);
}
}

Getting access to Button parent

I'm using a Button in a class. When the button is pressed, it should call a routine with the button's corresponding text. How do I convert the sender into a String_Entry? Also, I'm quite a newbie regarding object oriented/class programming, so comments are welcome.
public class String_Entry
{
public TextBox textbox;
public Button send;
// other stuff
public String_Entry()
{
textbox = new TextBox();
send = new Button();
send.Click += new System.EventHandler(this.bSend_Click);
// put in GUI, set parameters and other stuff
}
// other stuff
private void bSend_Click(object sender, EventArgs e)
{
// Trying to get the corresponding String_Entry from the Button click event
Button cntrl = (Button)sender;
String_Entry entry = (String_Entry)(cntrl.Parent);
parse.ProcessHexLine(entry);
}
}
Your solution of encapsulating a button with a textbox and the event handler is sound. It just goes wrong in the event handler:
private void bSend_Click(object sender, EventArgs e)
{
Button cntrl = (Button)sender;
String_Entry entry = (String_Entry)(cntrl.Parent);
parse.ProcessHexLine(entry);
}
Firstly, there is no point to doing anything with sender as it'll be the same as the field send. Next cntrl.Parent will give you a reference to the Form, or other container object, that contains the button, not this instance of String_Entry. To access that, use this. So you can change the event handler to:
private void bSend_Click(object sender, EventArgs e)
{
parse.ProcessHexLine(this);
}

C# editable listview

Yesterday I try to implement a new listview that support sub-item edit, my solution is to show a textbox when double click the sub-item. The key code as following:
protected override void OnDoubleClick(EventArgs e)
{
Point pt = this.PointToClient(Cursor.Position);
ListViewItem curItem;
int subItemIndex = GetSubItemAt(pt.X, pt.Y, out curItem);
DoubleClickEventArgs args = new DoubleClickEventArgs(subItemIndex);
base.OnDoubleClick(args);
if (subItemIndex>=0 && !args.Cancel)
{
//StartEdit(...);
}
}
public void EndEdit(bool acceptChanges)
{
//validation
.................
.................
AfterSubItemEventArgs e = new AfterSubItemEventArgs(this.SelectedItems[0], m_editSubItemIndex, this.SelectedItems[0].SubItems[m_editSubItemIndex].Text, m_textbox.Text, false);
OnAfterSubItemEdit(e);
if (e.Cancel)
{
//....
}
else
{
//set new value
}
m_textbox.Visible = false;
m_editSubItemIndex = -1;
}
OnAfterSubItemEdit is a event that user can do some validations or other operations. I add a check in this method, if the new value exist, I will show a messagebox to user firstly, then hide the textbox. But now, the problem comes, when i move the mouse, the listview items can be selected, I don't how to solve this issue, I tried my best to find out the way, but failed. So, please help me!
Listview has a LabelEdit property; when you set it "true", then in an event handler you can call Listview.Items[x].BeginEdit(), and edit an item. As an example, you can handle ListView.DoubleClick event and call BeginEdit right there:
private void Form1_Load(object sender, System.EventArgs e)
{
listView1.LabelEdit = true;
}
private void listView1_DoubleClick(object sender, System.EventArgs e)
{
if(this.listView1.SelectedItems.Count==1)
{
this.listView1.SelectedItems[0].BeginEdit();
}
}
The problem is that your form still calls the DoubleClick event whether the value exists or not. Add appropriate condition before calling base DoubleClick in your code, i.e.:
if(!new value exists)
base.OnDoubleClick(args);

Categories