Custom Zedgraph ToolStripMenuItem won't check when clicked - c#

I customize the right click menu thanks to this :
lineGraphControl1.ContextMenuBuilder += new ZedGraphControl.ContextMenuBuilderEventHandler(MyContextMenuBuilder);
And
private void MyContextMenuBuilder(ZedGraphControl control, ContextMenuStrip menuStrip, Point mousePt, ZedGraphControl.ContextMenuObjectState objState)
{
// create a new menu item
ToolStripMenuItem item = new ToolStripMenuItem();
// This is the user-defined Tag so you can find this menu item later if necessary
item.Name = "simple_cursor";
// This is the text that will show up in the menu
item.Text = "Simple Cursor";
item.CheckOnClick = true;
// Add a handler that will respond when that menu item is selected
item.Click += new System.EventHandler(DisplaySimpleCursor);
// Add the menu item to the menu
menuStrip.Items.Add(item);
}
But the menu Simple Cursor won't check when clicked. I try to force the sender in the function DisplaySimpleCursor(), it doesn't work.
When I debug my app, I see that in DisplaySimpleCursor(), the sender's property Checked is set to true.
What am I missing ?

As the menu is build on the heat, the checkOnClick means nothing since the object is destroyed (I guess) everytime the menu is hidden.
The solution was to set the property :
// showOneCursor is a bool describing my need and toggled on click
item.Checked = showOneCursor;

Try this.
private bool check;
public bool Check
{
get { return check; }
set { check= value; }
}
private void MyContextMenuBuilder(ZedGraphControl control, ContextMenuStrip menuStrip, Point mousePt, ZedGraphControl.ContextMenuObjectState objState)
{
ToolStripMenuItem item = new ToolStripMenuItem();
item.Name = "simple_cursor";
item.Text = "Simple Cursor";
item.CheckOnClick = true;
item.Checked = Check; //add this
item.Click += new System.EventHandler(DisplaySimpleCursor);
menuStrip.Items.Add(item);
}
private void DisplaySimpleCursor(object sender, EventArgs e)
{
Check = false==Check;
}

Related

How to change menuitem tooltip text while tooltip active?

I have a first order menu item that is a chevron for toggling the state of a title panel. The menu item has ToolTipText that I want to change while the tool tip window is still open (i.e. hover active).
Is there a way to make this happen ?
Code
topMenuStrip.ShowItemToolTips = true;
chevronMenuItem.ToolTipText = "Hide title";
chevronMenuItem.Click += new System.EventHandler(titleToggle_Click);
private void titleToggle_Click(object sender, EventArgs e)
{
var mi = (ToolStripMenuItem)sender;
if (titlePanel.Visible)
{
titlePanel.Visible = false;
mi.ToolTipText = "Show title bar"; // does not change while hover active
mi.Image = Properties.Resources.chevron_expand;
}
else
{
titlePanel.Visible = true;
mi.ToolTipText = "Hide title bar"; // does not change while hover active
mi.Image = Properties.Resources.chevron_collapse;
}
}
Pictures
Third image is after the tooltip is rerendered after new hover (mouse leave chevron mouse enter chevron)
According to Microsoft documentation, you must set the property AutoToolTip = false and the property ShowItemToolTips = true.
ToolStripItem uses the Text property as the default source for the
ToolTip content. Set AutoToolTip to false to use ToolTipText as the
source for ToolTip content.
To use this property, you must also set ShowItemToolTips to true.
Source: ToolStripItem.AutoToolTip Property

NavigationView change selected item using back button

I'm using a navigationview control in a UWP app, the thing is when I click the back button the focused element doesn't change to the item displayed in the contentframe. For example the clicked elements were camara, store, musica, then back button twice to display camara in the contentframe element, but musica still has the focus (blue rectangle)
private void FrameNavigated( object sender, NavigationEventArgs e )
{
var currentView = SystemNavigationManager.GetForCurrentView();
if ( ContentFrame.CanGoBack )
{
currentView.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
}
else
{
currentView.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Collapsed;
}
}
private void OnBackRequested( object sender, BackRequestedEventArgs e )
{
if ( ContentFrame.CanGoBack )
{
e.Handled = true;
PageStackEntry pageStackEntry = ContentFrame.BackStack.LastOrDefault();
ContentFrame.GoBack();
if ( pageStackEntry != null )
{
string nombre = pageStackEntry.SourcePageType.Name;
MenuItem item = subItemsMenu.FirstOrDefault(nom => nom.NombrePantalla.Equals(nombre));
navView.SelectedItem = item;
navView.Header = item.Encabezado;
}
}
}
Solved, using
NavigationViewExtensions.SetSelectedIndex(NavigationView, index); from Microsoft.Toolkit.Uwp.UI.Extensions 4.0.0, since 5.0.0 version is deprecated
I didn't see any problem in your code. Several ways may help to troubleshooting:
Debug and make sure MenuItem item is not null.
When back button is clicked, try select home or camera directly by your code
private void OnBackRequested( object sender, BackRequestedEventArgs e )
{
string nombre = "Camera";
MenuItem item = subItemsMenu.FirstOrDefault(nom => nom.NombrePantalla.Equals(nombre));
navView.SelectedItem = item;
}
Add SelectionChanged="nav_SelectionChanged" to the XAML and then check SelectionChanged
Post a simple app which can repro your problem

MenuItem AutoClose = false on dynamically generated Toolstrip Menu

So, following this question, I have been attempting to deal with a way to stop a drop down menu from closing when I click on an item.
In the linked question, one such answer suggested that I set the AutoClose property to false. I did so, and this did achieve what I asked. However, the way I implemented it means that the Drop Down menu is forced open.
Form Code:
public void ToolStripMenuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem item = sender as ToolStripMenuItem;
if (item != null)
item.Checked = !item.Checked;
item.DropDown.AutoClose = false;
}
I know why this is - the implementation means that there is no way to allow the AutoClose to be set to true. However, since the menuItems are dynamically generated in a different class, I don't have any events or objects to refer to.
This code copies the menu structure from the Main Form, and copies it across to recreate it in the "Profile View" (to set what users can/cannot see).
Controller Code:
private void PopulateProfileView(User_AccessProfilesView view, Menu_View mainMenu)
{
// Disabled Items are not able to be set, becasue they are either always visible for every user,
// or only visible to specific users (Administrator)
List<string> disabledMenuItems = new List<string>();
List<string> disabledSubMenuItems = new List<string>();
bool error = false;
bool subError = false;
_groupDictionary = new Dictionary<string, List<string>>();
// Populate the disallowed Menu Items from the Main Menu,
// and then add the items specific to the Profile View
disabledMenuItems.Add("File");
disabledMenuItems.Add("Administrator");
disabledMenuItems.Add("Help");
disabledMenuItems.Add("Te&rminations");
disabledMenuItems.AddRange(mainMenu.disallowedMenuItems);
// Populate the disallowed Sub Menu Items from the Main Menu,
// and then add the items specific to the Profile View
disabledSubMenuItems.Add("View All");
disabledSubMenuItems.AddRange(mainMenu.disallowedSubItems);
foreach (ToolStripMenuItem item in mainMenu.mainMenuStrip.Items)
{
ToolStripMenuItem menuItem = new ToolStripMenuItem(item.Text);
if (error == false)
{
// Add to the menu bar
view.menuStrip.Items.Add(menuItem);
menuItem.Click += new EventHandler(view.ToolStripMenuItem_Click);
foreach (ToolStripItem dropItem in item.DropDownItems)
{
if (dropItem is ToolStripMenuItem)
{
ToolStripMenuItem menuDropItem = new ToolStripMenuItem(dropItem.Text);
// Same concerns as above with regards to doing a substring check
// to decide if menu items should be excluded or not.
foreach (string s1 in disabledSubMenuItems)
{
if (!menuDropItem.Text.Contains(s1))
{
subError = false;
}
else
{
subError = true;
break;
}
}
if (!subError)
{
menuItem.DropDownItems.Add(menuDropItem);
menuDropItem.Click += new EventHandler(view.ToolStripMenuItem_Click);
}
}
else if (dropItem is ToolStripSeparator)
{ menuItem.DropDownItems.Add(new ToolStripSeparator()); }
}
How do I implement the AutoClose property correctly so that if I click on a menu item, the menu won't close, but if I click on the menu header, or move the mouse away from the menu, or select another menu (either by click or mouse over), the menu does Close?
Apologies if this is a simple issue - I have been out of the game for roughly a year, and have to jump back into this and I am having a little bit of an issue following everything properly.
To solve the problem you can follow these steps:
You should determine which menu items should keep open even after clicking on them. I'll use "keepopen" as value of Tag property for those items that should be kept open after clicking.
For the menu item which contains those items, you need to get DropDown property and and handle its ItemClicked event and in the ItemClicked event, you should check if the item which is clicked is one of those "keepopen" items, then set DropDown.AutoClose of the container menu item to false. For other items, set it to true. It will prevent closing those "keepopen" item when clicking, while let other items close by click.
You should handle CheckedChanged event of those "keepopen" items and set DropDown.AutoClose to true. While using the Click event handler we prevented the items from closing, here we enable the closing again, so if the user click outside of the menu, it will close.
Then this would be the result, look at mouse clicks:
Example
As an example, create an empty form and handle its Load event and use following code. When you click on SubMenu1, SubMenu2 or SubMenu3, they will just get checked or unchecked without closing the menu. But of you click outside the menu or on SubMenu4, it will close the menu.
const string keepopen = "keepopen";
private void Form1_Load(object sender, EventArgs e)
{
var menuStrip = new MenuStrip() { Dock = DockStyle.Top };
this.Controls.Add(menuStrip);
var menu1 = (ToolStripMenuItem)menuStrip.Items.Add("Menu1");
menu1.DropDownItems.Add(new ToolStripMenuItem("Submenu1")
{ Tag = keepopen, CheckOnClick = true });
menu1.DropDownItems.Add(new ToolStripMenuItem("Submenu2")
{ Tag = keepopen, CheckOnClick = true });
menu1.DropDownItems.Add(new ToolStripMenuItem("Submenu3")
{ Tag = keepopen, CheckOnClick = true });
menu1.DropDownItems.Add("-");
menu1.DropDownItems.Add(new ToolStripMenuItem("Submenu4"));
menu1.DropDown.ItemClicked += (obj, args) =>
{
if (args.ClickedItem.Tag == keepopen)
menu1.DropDown.AutoClose = false;
else
menu1.DropDown.AutoClose = true;
};
menu1.DropDownItems.OfType<ToolStripMenuItem>()
.Where(x => x.Tag == keepopen)
.ToList().ForEach(x =>
{
x.CheckedChanged += (obj, args) =>
{
menu1.DropDown.AutoClose = true;
};
});
}

Adding/Removing events based on context

I am new to C# and WinForms. I have some objects with the right click (context menu) events. However, depending on the context (for example depending on whether the user is in the wizard screen or the main screen), I want to alter what the right click does. I googled a bit and found that I can use += and -= operators but I still could not achieve what I want to do. Given the code below, for example,
Any ideas ?
EDIT: I want the OnClickCard behave differently in different places.
Sammple Code:
public override ContextMenuStrip GetContextMenuStrip(GoView view)
{
if (Selectable)
{
ContextMenuStrip contextMenu = new ContextMenuStrip();
if (!Empty)
{
// this is just for example so not showing the implementation
contextMenu.Items.Add(new ToolStripMenuItem(
"Delete",
null,
new EventHandler(OnClickDelete)));
}
// Empty
else
{
ToolStripMenuItem addCard = new ToolStripMenuItem("Add");
foreach (..some data..)
{
ToolStripMenuItem card = new ToolStripMenuItem(
data,
null,
new EventHandler(OnClickCard));
addCard.DropDownItems.Add(card);
}
}
}
else
{
return null;
}
}
private void OnClickCard(object sender, EventArgs e)
{
ToolStripMenuItem cardItem = (ToolStripMenuItem)sender;
if (cardItem.Text.Contains("ABC"))
{
Common.Forms.FormMMUSettings f = new FormMMUSettings(cardItem.Text,ParentMagazine.NextSite);
f.Show();
}
SetCard(new MagazineCard(2, cardItem.Text));
}
Are you saying you want to change the contents of the context menu depending on the circumstances when it's clicked? If so, the easiest way is to create multiple context menus, and just use an event to set whichever context menu you want.
ContextMenu menu1 = new ContextMenu();
MenuItem menu1Item1 = new MenuItem();
menu1Item1.Header = "Menu 1 Item 1";
menu1Item1.Click += new RoutedEventHandler(menu1Item1Clicked);
menu1.Items.Add(mnu1Item1);
MenuItem menu1Item2 = new MenuItem();
menu1Item2.Header = "Menu 1 Item 2";
menu1Item2.Click += new RoutedEventHandler(menu1Item2Clicked);
menu1.Items.Add(menu1Item2);
ContextMenu menu2 = new ContextMenu();
MenuItem menu2Item1 = new MenuItem();
menu2Item1.Header = "Menu 2 Item 1";
menu2Item1.Click += new RoutedEventHandler(menu2Item1Clicked);
menu2.Items.Add(menu2Item1);
MenuItem menu2Item2 = new MenuItem();
menu2Item2.Header = "Menu 2 Item 2";
menu2Item2.Click += new RoutedEventHandler(menu2Item2Clicked);
menu2.Items.Add(menu2Item2);
public void menu1Item1Clicked(object sender, EventArgs e)
{
}
etc..
Now you can just set whichever menu you need using:
myForm.ContextMenu = menu1;
Hope this helps.
+= and -= should work just fine but I'd suggest you to use a kind of handlers repo where you'd switch which handler to use. This should work like a strategy pattern where different wizard steps would be different strategies.
It would be easier to help you if you'll show us some code and point us which code parts do not work properly.
You seem to suggest that you would like to attach different handlers depending on context:
if(that)
obj.event += HandleThat;
else
obj.event += HandleSomethingElse;
That should work, but you can also do it in one handler:
obj.event += HandleAll;
void HandleAll(object sender, EventArgs arg) {
if(that)
HandleThat();
else
HandleSomethingElse();
}
EDIT: ok, your edited question really meant something else.
First obvious problem is that you add OnClickDelete as a handler, and show the implementation of OnClickCard which will not be called in your example. If it is a typo, then you just need to implement the handler method as you need. What part exactly is not working?

Setting ToolStripMenuItem.Visible to true doesn't work

I have a TreeView control for which each node in it I want to share a ContextMenuStrip which has two ToolStripMenuItems ie:
this.BuildTree = new MyApp.MainForm.TreeView();
this.ItemMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ShowLogMenuItem = new System.Windows.Forms.ToolStripMenuItem();
...
this.ItemMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.DeleteMenuItem,
this.ShowLogMenuItem});
So I show and hide these to items according to certain criteria on a right click in a MouseUp event. When both are hidden I hide the ContextMenuStrip itself. Problem is when I hide the ContextMenuStrip it seems the next time I want to show one of the menu items I have to click twice on the node. The strange thing is on the first click to reshow one or both of the the items I have the following code:
ItemMenuStrip.Visible = true;
ShowLogMenuItem.Visible = true;
The two lines above don't seem to do anything ie both remain false in the debugger view after stepping over each line.
I don't think I've got any events on these values being set at least I don't have any events attached.
What am I doing wrong?
I suggest you to set:
this.BuildTree.ContextMenuStrip = this.ItemMenuStrip;
to make the menu automatically open on tree right-click.
Then subscribe ItemMenuStrip.Opening event to change the visibility of items and the contextmenu itself:
void ItemMenuStrip_Opening(object sender, CancelEventArgs e)
{
if (something)
{
e.Cancel = true; // don't show the menu
}
else
{
// show/hide the items...
}
}
If you need to know the current position of the clicked point (e.g. to check if a tree node is clicked), you can use Control.MousePosition property. Note that MousePosition is a point in screen coordinates, so you need to call treeView1.PointToClient(position) to get the tree coordinates e.g. :
private void ItemMenuStrip_Opening(object sender, CancelEventArgs e)
{
var pointClicked = this.BuildTree.PointToClient(Control.MousePosition);
var nodeClicked = this.BuildTree.GetNodeAt(pointClicked);
if (nodeClicked == null)
{
// no tree-node is clicked --> don't show the context menu
e.Cancel = true;
}
else
{
// nodeClicked variable is the clicked node;
// show/hide the context menu items accordingly
}
}
So figured out what was going wrong I was setting Visible on this.ItemMenuStrip rather than the this.BuildTree.ContextMenuStrip.
This seems rather strange to me as I would have thought BuildTree.ContextMenuStrip was just a direct reference to the ItemMenuStrip but apparently not.

Categories

Resources