I have a ContextFlyout in my form and I want the listbox to select the index where the mouse is upon right-click
Originally I thought I could take advantage of the RightTapped event so I created an event handler, but while filling out the method, I didn't see any way to translate the position of the mouse to an item in the listbox.
RightTapped event
private void SideMenu_RightClick(object sender, RightTappedRoutedEventArgs e) {
ListBox menu = (ListBox)sender;
SideMenu.SelectedIndex = menu.IndexFromPoint(e.);
menu.
}
I've looked through all the methods and properties but I can't seem to find what I need. I found a lot of solutions for WPF, but this is UWP and those methods do not exist on these UWP objects
An easier approach would be to attach the event handler to the ListBoxItem or the root element in the ItemTemplate. You'll find an example of how you could do this here.
I figured out how to do it. Firstly, both my MenuFlyout and items for the listbox are generated programmatically.
Creating MenuFlyout
//this is a property in the class
internal MenuFlyout rightclick = new MenuFlyout();
//In Page's Constructor
this.InitializeComponent();
MenuFlyoutItem mfi = new MenuFlyoutItem();
mfi.Text = "Copy";
rightclick.Items.Add(mfi);
mfi = new MenuFlyoutItem();
mfi.Text = "Delete";
rightclick.Items.Add(mfi);
rightclick.Opened += rightclick_opened; //run method when flyout is opened
Method for the Opened event
private void rightclick_opened(object sender, object e) {
MenuFlyout mf = (MenuFlyout)sender;
SideMenu.SelectedItem = mf.Target; //makes the magic happen
}
Instantiating ListBoxItems
private void NewLocation(object sender, RoutedEventArgs e) {
Location newLocation = new Location(); //custom class
ListBoxItem nl = new ListBoxItem(); //creates empty ListBoxItem
nl.Content = newLocation.objectName; //give listboxitem default name from the class constructor
nl.ContextFlyout = rightclick; //set contextflyout for item
SideMenu.Items.Add(nl); //add new item to listbox
locations.Add(newLocation); //add new object to "linked" list
SideMenu.SelectedIndex = locations.Count - 1; //set current selected to new item
}
Related
I have this code i'm testing that's supposed to check a listview control for existing item and return a text "existing item" when it finds one, now I know it's possible to do this using loops but I want to learn to proper use the contains method and couldn't find any real explanation on how to use contains method on panels. the code does seem to work once I remove the stackpanel from the listview but once I add a panel of any type it doesn't seem to work anymore, and i'm really puzzled by why this is happening i'm sure i'm doing something wrong, would appreciate any help here's the code:
private void Test_Click(object sender, RoutedEventArgs e)
{
TextBlock testblock = new TextBlock();
testblock.Text = textBox6.Text;
StackPanel TestPanel = new StackPanel();
TestPanel.Children.Add(testblock);
if (listView.Items.Contains(TestPanel))
{
textBox5.Text = "existing item";
}
else
{
listView.Items.Add(TestPanel);
}
}
When you fire the Test_Click event by first time, it will create a new instance of the StackPanel. And then it will be added into the ListView.Items.
When you fire the Test_Click event again, it will create another new instance of the StackPanel. Which is not equal to the first instance of StackPanel. So the listView.Items.Contains(TestPanel) always return false.
We can define a field in MainPage class that named "TestPanel" and initialize it in the constructor like:
private StackPanel TestPanel;
private TextBlock testblock;
public MainPage()
{
this.InitializeComponent();
testblock = new TextBlock();
TestPanel = new StackPanel();
TestPanel.Children.Add(testblock);
}
private void Test_Click(object sender, RoutedEventArgs e)
{
if (listView.Items.Contains(TestPanel))
{
textBox5.Text = "existing item";
}
else
{
testblock.Text = textBox6.Text;
listView.Items.Add(TestPanel);
}
}
![enter image description here][1]I am trying to add a combobox to ContextMenu on a datagrid when a user right clicks, the menu will pop up. It should show exit and assign to bankID menu options where the bank ID is a combobox dropdown. I did some online search but couldn't find anything close which makes me wonder, it is even possible to do that. I created a mockup image of what I'm trying to do with some code. If anyone has done something similar and share with me, I would really appreciate it. Thanks.
private ContextMenu menuOpp = new ContextMenu();
private ComboBox cmbAssign = new ComboBox();
private int currentMouseOverRow;
private void dataGridView2_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
menuOpp.Name = "Exit";
menuOpp.MenuItems.Add("Exit", new EventHandler(menuItem_Click));
cmbAssign.Items.Add("assign");
dataGridView2.ContextMenu = menuOpp;
currentMouseOverRow = dataGridView2.HitTest(e.X, e.Y).RowIndex;
menuOpp.Show(dataGridView2, new Point(e.X, e.Y));
}
}
I was able to resolve this myself. I created a ContextMenuStrip, added a MenuItem with sub ComboBox item, populated the ComboBox on ToolStripMenuItem Click event. Then assigned ContextMenuStrip object to its ContextMenuStrip property. After assigning the ContextMenuStrip object to a control, the contextual menu displayed as user right click.
private void InitializeComponent()
{
System.Windows.Forms.ContextMenuStrip Context =
new System.Windows.Forms.ContextMenuStrip();
ToolStripMenuItem mnuAssign = new ToolStripMenuItem("Assign");
Context.Items.Add(mnuAssign);
ContextMenuStrip = context;
}
In my item template in longlistselector I have a hyperlink button.
When I'm clicking on button, that item should be deleted.
The problem is that if there is no selected item, I need to click twice on button, because after first click SelectedItem in LonglistSelector is null.
How to fix it, that click on button will automatically set selection on list to button's parent?
You can do this in two different ways (ignoring MVVM pattern). You can delete the item in the Click eventhandler of the HyperLinkButton or you can set the SelectedItem of the LongListSelector, so you can delete it right after.
public ObservableCollection<object> List { get; set; }
public MainPage()
{
InitializeComponent();
List = new ObservableCollection<object>() { "aaaa", "bbb", "cccc", "dddd", "eeee"};
LongList.ItemsSource = List;
}
private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
var hyperLinkButton = sender as HyperlinkButton;
var boundItemDataContext = hyperLinkButton.DataContext;
List.Remove(boundItemDataContext); // #1 Delete it directly from the list that automatically gets updated because it's an ObservableCollection.
LongList.SelectedItem = boundItemDataContext; // #2 Set the SelectedItem property to the current DataContext, so you can delete it in the SelectionChanged eventhandler.
}
private void LongList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var longListSelector = sender as LongListSelector;
List.Remove(longListSelector.SelectedItem);
}
I'm creating a ToolStripMenu shown below that is supposed to allow the user to interact with the items "XML" and "Non XML" as though they are regular check boxes on a form. However, when one item is checked/unchecked the menu closes. How can I allow an item to be checked/unchecked without closing the menu? Or is there a different standard method of achieving the same behavior?
So what I want is to be able to click on "Non XML", show a check box and leave the menu open.
The idea is that the last menu item will be "Done" and when it's clicked the "G2S" sub items will remain open but the "Display" sub items ( XML, Non XML ) will close.
Any ideas?
Note: I am aware that this is likely not the best user interface design. I'd like to know however how this could be accomplished just to gain some technical knowledge about handling menus.
Interesting concept is described in this thread on Stackoverflow:
Here is the essence of the accepted answer:
ParentMenu.DropDown.AutoClose = false;
It does exactly what you are asking for - prevent menu from closing when subitem is clicked.
Here's a useful extension that requires user to click outside of menu item + dropdowns to close.
public static void KeepOpenOnDropdownCheck (this ToolStripMenuItem ctl)
{
foreach (var item in ctl.DropDownItems.OfType<ToolStripMenuItem>())
{
item.MouseEnter += (o, e) => ctl.DropDown.AutoClose = false;
item.MouseLeave += (o, e) => ctl.DropDown.AutoClose = true;
}
}
Posted in case somebody finds it helpful.
Instead of trying to do exactly what I had originally intended, I've come up with the following:
1- Use a ContextMenuStrip
2- When the user clicks on the ToolStripMenu item I display the ContextMenuStrip at a location near the menu item as shown below: ( note the positioning still needs adjusting )
To get this working I build the ContextMenuStrip in code at run-time so that the items in the ContextMenuStrip can be build dynamically based on the situation.
Code snippets:
Show the ContextMenuStrip when the menu item is clicked:
private void filterToolStripMenuItem_Click(object sender, EventArgs e)
{
contextMenuStrip1.Show(this, 180, 20);
}
Build the ContextMenuStrip:
if (protInfo.Name == "QCOM" )
{
BroadCast = new CheckBox();
BroadCast.Text = "Date/Time Broadcast";
BroadCast.Checked = FlagSet(CurrentFilter, (Byte)Filter.DateTimeBC);
ToolStripControlHost Ch1 = new ToolStripControlHost(BroadCast);
GenPoll = new CheckBox();
GenPoll.Text = "Status Poll";
GenPoll.Checked = FlagSet(CurrentFilter, (Byte)Filter.GenStatusPoll);
ToolStripControlHost Ch2 = new ToolStripControlHost(GenPoll);
GenPollResp = new CheckBox();
GenPollResp.Text = "Status Poll Response";
GenPollResp.Checked = FlagSet(CurrentFilter, (Byte)Filter.GenStatusResponse);
ToolStripControlHost Ch3 = new ToolStripControlHost(GenPollResp);
Button btnDone = new Button();
btnDone.Text = "Done";
ToolStripControlHost Ch4 = new ToolStripControlHost(btnDone);
btnDone.Click += new EventHandler(btnDone_Click);
contextMenuStrip1.Items.Clear();
contextMenuStrip1.Items.Add(Ch1);
contextMenuStrip1.Items.Add(Ch2);
contextMenuStrip1.Items.Add(Ch3);
contextMenuStrip1.Items.Add(Ch4);
contextMenuStrip1.Enabled = true;
filterToolStripMenuItem.Enabled = true;
}
else
{
filterToolStripMenuItem.Enabled = false;
}
This may not be the best user interface design, but it seems to work.
The original solution will work with the use of mouse events.
On mouse enter event:
parent.dropdown.autoclose = false;
on mouse leave event:
parent.dropdown.autoclose = true;
The only catch is if the user access the menu items by other means than a mouse.
I used a combination of Neolisk's and Chimera's answers to allow deletion of multiple leaf items from a treeview. My solution is below
Note: the following Items created at design time are used:
TreePromotions (TreeView)
menuVendorSection (Context Menu Strip)
removeMultipleItemsToolStripMenuItem (DropDown of menuVendorSection)
private void removeMultipleItemsToolStripMenuItem_MouseHover(object sender, EventArgs e)
{
removeMultipleItemsToolStripMenuItem.DropDownItems.Clear();
ToolStripMenuItem detailMenuItem;
TreeNode vendorSectionNode = treePromotions.SelectedNode;
for (int vsn = 0; vsn < vendorSectionNode.Nodes.Count; vsn++)
{
//add checkbox item
detailMenuItem = new ToolStripMenuItem(vendorSectionNode.Nodes[vsn].Text);
detailMenuItem.Tag = vendorSectionNode.Nodes[vsn].Tag;
detailMenuItem.CheckOnClick = true;
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(detailMenuItem);
}
//add action buttons
Button buttonDeleteMultiple = new Button();
buttonDeleteMultiple.Text = "Remove Checked Items";
ToolStripControlHost buttonHost = new ToolStripControlHost(buttonDeleteMultiple);
buttonDeleteMultiple.Click += new EventHandler(buttonDeleteMultiple_Click);
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(buttonHost);
Button buttonCancelMultipleDelete = new Button();
buttonCancelMultipleDelete.Text = "CANCEL";
buttonHost = new ToolStripControlHost(buttonCancelMultipleDelete);
buttonCancelMultipleDelete.Click += new EventHandler(buttonCancelMultipleDelete_Click);
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(buttonHost);
removeMultipleItemsToolStripMenuItem.DropDown.AutoClose = false;
menuVendorSection.AutoClose = false;
}
private void buttonDeleteMultiple_Click(object sender, EventArgs e)
{
//delete items
for (int dmi = 0; dmi < removeAllItemsToolStripMenuItem.DropDownItems.Count - 2; dmi++) //do not include buttons
{
((Detail)removeAllItemsToolStripMenuItem.DropDownItems[dmi].Tag).Delete(); //deletes item from database
}
//rebuild leaf
treePromotions.SelectedNode.Nodes.Clear();
addItemNodes(treePromotions.SelectedNode); //builds leaf nodes from database
//close menus
removeMultipleItemsToolStripMenuItem.DropDown.Close();
menuVendorSection.AutoClose = true;
menuVendorSection.Close();
}
private void buttonCancelMultipleDelete_Click(object sender, EventArgs e)
{
//just close menus
removeMultipleItemsToolStripMenuItem.DropDown.Close();
menuVendorSection.AutoClose = true;
menuVendorSection.Close();
}
If someone is still interested, here is a vb solution:
1) For the parent tool strip menu item, add the following handler in the form's constructor:
AddHandler ParentTSMI.DropDown.Closing, AddressOf onDropDownClosing
2) The handler:
Private Sub onDropDownClosing(sender As Object, e As ToolStripDropDownClosingEventArgs)
If e.CloseReason = ToolStripDropDownCloseReason.ItemClicked Then
e.Cancel = True
End If
End Sub
That's it all.
Don't forget to remove the handler (RemoveHandler) when you close the form.
I've got a TreeView, containing a number of levels of TreeViewItems.
I would like to add a context menu to only one level of items in the TreeView. However, my code produces a result whereby every single item in the TreeView has a context menu.
This is my code:
//.... foreach item in this level....
{
ContextMenu cmDatabase = new ContextMenu();
MenuItem menuItem = new MenuItem();
menuItem.Header = "Close Connection";
Image imgMenuIcon = new Image();
imgMenuIcon.Source = new BitmapImage(new Uri("icon.png"));
menuItem.Icon = imgMenuIcon;
cmDatabase.Items.Add(menuItem);
treeViewItem.ContextMenu = cmDatabase;
}
I've also tried manually setting all the other TreeViewItems' contextMenu property to null. No luck though. Any ideas?
The TreeView has a ContextMenuOpening event. Set the Handled property of the event handler argument e to true depending on the tree level. This will discard the context menu.
private void treeView1_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
e.Handled = <tree level does not require a context menu>;
}
If you have a TextBlock for your TreeViewItem, you can attach the ContextMenu onto that instead.
Textblock header = "TreeViewItem Text";
header.ContextMenu = cmDataBase;
treeViewItem.Header = header;
Also, for your other question that I answered, but you deleted before I hit Save. :P I'd put the right-click as an event (also on the header).
header.MouseRightButtonDown += new MousebuttonEventHandler(rightClickSelection);
private void rightclickSelection(object sender, MouseButtonEventArgs e) {
TreeViewItem clickedParent = (sender as TextBlock).Parent as TreeViewItem;
clickedParent.IsSelected = true;
clickedParent.UpdateLayout();
}