I'm trying to make a list of items that you can do several actions with by right-clicking and having a context menu come up. I've completed that, no problem whatsoever.
But I'd like to have it so that when you right click on a item, instead of leaving the current item selected, to select the item the mouse is over.
I've researched this and other related questions, and I've tried to use indexFromPoint (which I found through my research) but whenever I right click on a item, it always just clears the selected item and doesn't show the context menu, as I have it set so that it wont appear if there is no selected item.
Here is the code I'm currently using:
ListBox.SelectedIndex = ListBox.IndexFromPoint(Cursor.Position.X, Cursor.Position.Y);
Handle ListBox.MouseDown and select the item in there. Like this:
private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
listBox1.SelectedIndex = listBox1.IndexFromPoint(e.X, e.Y);
}
this one is working...
this.ListBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.List_RightClick);
private void List_RightClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
int index = this.listBox.IndexFromPoint(e.Location);
if (index != ListBox.NoMatches)
{
listBox.Items[index];
}
}
}
Can also get same behaviour by setting a MouseRightButtonUp event on the whole listbox then:
private void AccountItemsT33_OnMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
// If have selected an item via left click, then do a right click, need to disable that initial selection
AccountItemsT33.SelectedIndex = -1;
VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(null), (sender as ListBox)).OfType<ListBoxItem>().First().IsSelected = true;
}
Related
So I have a form DataGridView and when I right click on the grid I want to display a context menu that has one menu item in it. The menu item will open a second form that will provide some configuration options for the DataGridView.
Now all of this works absolutely fine, the context menu displays correctly and the second form opens correctly and all of the functionality on that form works correctly.
The only issue is that the context menu will only close if I click anywhere other than the menu item. No matter how many times I click on the menu item the context menu does not close.
I have tried looking for work arounds but as far as I can tell there is no way to programatically close the context menu.
Any help would be greatly appreciated. Below are copies of the click events for opening the context menu and for the menu item click event.
private void DataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
DataGridView dgv = (DataGridView)sender;
if (dgv.CurrentCell == null)
{
return;
}
else
{
Rectangle r = dgv.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false);
Point p = new Point(r.X + e.X, r.Y + e.Y);
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add(new MenuItem("Item", Item_Click));
cm.Show(dgv, p);
}
}
}
private void Item_Click(object sender, EventArgs e)
{
new SecondForm().Show();
}
UPDATE:
I solved the issue by replacing the ContextMenu class with the ContextMenuStrip class, removing the MouseClick event handler and assigning the ContextMenuStrip object to DataGridView.ContextMenuStrip. It appears as though the ContextMenuStrip class deals with showing the menu when it's relevant control is right clicked, so if you add a click event handler to deal with opening the menu it will repeatedly try to render the menu making it flicker several times before it is eventually rendered
in your class add a private variable
private bool CloseMenu = true;
on mouse down of your Context Menu
private void Item_Click(object sender, EventArgs e)
{
CloseMenu = false;
new SecondForm().Show();
}
add context menu closing event
private void contextMenuStripMy_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
e.Cancel = !CloseMenu;
CloseMenu = true;
}
I found some workdaround on this problem after many trials.
Firstly, this is about ContextMenu and not ContextMenuStrip.
This is not perfect solution but it works good if you do not have other alternative solution.
Here is how.
Just Set Visiable = false for all MenuItems under the Context Menu.
Only one problem with this is that it shows small square around the mouse.
I think this small square is the empty context menu box.
However, this small square will be removed quickly if user clicks anywhere and if the context menu lose focus.
It is really small and not bothering.
In code, this will look something like this in case you have only one menu item.
if (cm != null)
{
if (cm.MenuItems.Count > 0) cm.MenuItems[0].Visible = false;
}
If you have multiple of items, then just loop through all menu items.
if (cm != null)
{
for(int i = 0; i < cm.MenuItems.Count ; i++)
cm.MenuItems[i].Visible = false;
}
Hope this helps.
It worked for my case.
So I did not have to swtich to ContextMenuStrip from ContextMenu.
How to remove selected item in ComboBox with right click, when dropdown is opened?
Problem is that when you use event SelectedIndexChanged it doesn't have MouseEventArg as parameter, that mean you can't define which mouse button is pressed.
On the other side, when you use event MouseDown it can't detect when SelectedIndexChanged. In only one case MouseDown work when you press Button.Right and it is when you click on the ComboBox which don't have opened dropdown menu (basically right click on ComboBox).
Do you have some advice?
What I've tried so far:
private void combobox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
MessageBox.Show("mouse up");
}
private void combobox1_SelectedIndexChanged(object sender, EventArgs e)
{
if ((cmbSearch.SelectedIndex) != (-1))
{
combobox1.Items.RemoveAt(cmbSearch.SelectedIndex);
}
}
I've set comboBox with bunch of items and made it drop down list.
I've added handler to MouseDown event
private void comboBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Right)
return;
comboBox1.SelectedIndex = -1;
}
What this does, if any item selected, when you right click on the comboBox, it deselects selected item.
Now, how you handle this change in your SelectedIndexChanged is completely different item. Hope this answers your question.
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;
}
I am having my Listview as follows
Header1 Header2 Header3
Item1 Item2 Item3
Item1 Item2 Item3
Item1 Item2 Item3
I have written a code to show context menu on clicking the list view but it is showing the Context menu on headers too. I need to display Context menu only when user clicks on Items of list view can any one help me
This is my code I written at present
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
contextMenuStrip1.Show(listView1, e.Location);
}
How about this?
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
ListView listView = sender as ListView;
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
ListViewItem item = listView.GetItemAt(e.X, e.Y);
if (item != null)
{
item.Selected = true;
contextMenuStrip1.Show(listView , e.Location);
}
}
}
This sets it up so the context menu only shows if the right click happens on an item, because if the right click happens on a header or something else then item will be null. Hope it helps
This could be useful for you
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
if (listView1.FocusedItem.Bounds.Contains(e.Location) == true)
{
contextMenuStrip1.Show(Cursor.Position);
}
}
}
The "Bounds" property is a rectangle that represents the edges of the "FocusedItem" in pixels. So if the cursor is in this rectangle area when mouse right clicked then the "contextMenuStrip1" shows up.
You can cancel the viewing of the context menu if there are no items selected, which will be valid only if you right click an item
/// <summary>
/// ContextMenuStrip Opening Action
/// </summary>
private void listContextMenuStrip_Opening(object sender, CancelEventArgs e)
{
// If there are no items selected, cancel viewing the context menu
if (connectionListView.SelectedItems.Count <= 0)
{
e.Cancel = true;
}
}
This is quite dirty...just using the information at hand. Someone will probably come with a better answer.
private void listView1_MouseClick(object sender, MouseEventArgs e)
{
if ( e.Location.Y > headerHeightDefinedEarlier )
contextMenuStrip1.Show(listView1, e.Location);
}
You should to select the item when you are doing click on it. Then you may ask for the selecteditems in the list and get the selected element index: listView1.SelectedItems[0].Index
if (listView1.SelectedItems[0].Index == 0)
return;
I like to have a context menu only show up if an item is actually selected in a listbox in a winforms c# application.
Currently, I am able to select an item if it is right clicked properly, and I can disable the right click menu if nothing is selected, however, I don't want the menu to even show up.
how can this be accomplished?
private void genPassMenu_Opening(object sender, CancelEventArgs e)
{
genPassMenu.Enabled = lstPasswords.SelectedIndex > 0;
genPassMenu.Visible = lstPasswords.SelectedIndex > 0;
}
I tried both of those situations on their own, and it only works for enabled.
Perhaps Opening isn't the correct event to choose?
Tx
Try this:
private void genPassMenu_Opening(object sender, CancelEventArgs e)
{
//if (lstPasswords.SelectedIndex == -1) e.Cancel = true;
e.Cancel = (lstPasswords.SelectedIndex == -1);
}
Easy,
private void genPassMenu_Opening(object sender, CancelEventArgs e)
{
e.Cancel = (lstPasswords.SelectedIndex == 0);
}
I typically set the properties of each context menu item according to its appropriateness for the particular GUI element that is selected. Perhaps by setting the visible attribute on each menu item, rather than the whole menu, you can get the results that you want.
private void genPassMenu_Opening(object sender, CancelEventArgs e)
{
//genPassMenu.Enabled = lstPasswords.SelectedIndex > 0;
//genPassMenu.Visible = lstPasswords.SelectedIndex > 0;
e.Cancel = (lstPasswords.SelectedIndex <= 0);
}
I saw when the above did hte opposite I reversed the code slightly. For some reason having the equality also didn't work.