Systray context menu - why are my commands not enabled? - wpf

I'm creating a WPF app and have a system tray icon with a context menu. For the menu items I want to use WPF commands but when I assign them they are always greyed out even though the (same) commands are enabled in other places.
MenuItem menuItem = new MenuItem();
menuItem.Header = "Exit";
menuItem.Command = CustomCommands.ExitApplication;
Systray.AddMenuItem(menuItem);
It works fine when I assign click events and I have tried to create a CanExecute method for the command which always sets CanExecute to true, but that doesn't help either. Anyone got an idea why the menu items are disabled?
Update: As suggested, I added a command binding to the context menu. This had the effect that it works but only after you have clicked on the menu, i.e., at first the menu items are greyed out but once you click somewhere on the menu the options become enabled.
To solve this problem I called the following, after I added the menu items to the context menu:
CommandManager.InvalidateRequerySuggested();

Of the top of my head I'd guess you have to add a CommandBinding to the Menu or systray so that your command gets handled. Although I think if that were the case it would be enabled by default.

Yea I've seen this occur. Sometimes you have to tell the WPF CommandManager system to rerun the CanExecute methods. Try calling this once the ContextMenu is loaded: CommandManager.InvalidateQuerySuggested();

I had a similar issue. I feel my solution it's a bit of a hack, but I could really not get around this problem. I'm using a custom DelegateCommand implementation, and ebabling/disabling buttons and menu items works except for items in context menus. So, what I did was to handle the ContextMenuOpening event, then store the Items in a temp variable, call the Clear method in the ContextMenu and re-add the items right after. Works like a charm, but like I said, feels "hacky". It goes something like this:
private void ContextMenu_ContextMenuOpening (object sender, System.ComponentModel.CancelEventArgs e)
{
// HACK: For some reason items need to be removed and added back so that the command enablement requery works.
var menu = sender as ContextMenu;
if (menu == null) return;
var menuItems = menu.Items.ToArray();
menu.Items.Clear();
foreach (var menuItem in menuItems)
menu.Items.Add(menuItem);
}

Related

Prevent drop-down menu to close

I have a big problem. I want to prevent an opened drop-down menu to close when hovering another menu item. How can I achieve this? Thanks.
Regards
Marius
You should have a look at the event that's called when you are hovering another item, probably LostFocusor LostMouseCapture, look at the function called aith this event (OnLostFocus or OnLostMouseCapture) and override this method like this :
public override void OnLostFocus()
{
base.OnLostFocus();
Popup popup = Template.FindName("PART_Popup", this) as Popup;
popup.IsOpen = true;
}
This way, the event won't close the drop down menu. (The example above is for a combobox)
I'm not sure about the right event to override. It depends on your problem. You can find the list of event here if these are not the right ones. But I think that's the way you should do it.

WPF Tab_selectionChanged

I have this strange issue I am facing currently.
I have created an WPF application based on WPF page navigation. I have few button and depending on the button click the the user is navigated to respective WPF page.
In these WPF pages I have Tab controls and have used selectionchanged event handler to perform some task.
Now to the issue,
When I try to go a particular page, the selectionchanged event is also executed even before the page is loaded completely, I have tried to use the windows.loaded (based on the answer provided to my previous question - here) - I have no luck.
[I am using WPF Navigation framework]
Somehow the selectionchanged event is executing twice.
How do I stop this from happening?
I think you should check SelectionChange.AddedItems and SelectionChange.RemovedItems to find the difference between these to firings. I guess that when you select a page, SelectionChange.RemovedItems==0 while when you click on a tabItem to select it, SelectionChange.RemovedItems==1. if so just write:
if (SelectionChange.RemovedItems==0)
return;
Edit1: Please see the first comment.
Edit 2
void tablcontrol_SelectionChange(object sender, SelectionChangedEventArgs e)
{
if (e.RemovedItems.Count == 0)
{
// I guess this is the event that happens when a page is selected
// in this case just a TabItem is added to the selection
// and nothing is removed, so do nothing
return;
}
// if you are here, it means that this is another selection changed event
// so Perform those tasks that you mentioned in your question
}

WP7 - Cancelling ContextMenu click event propagation

I'm having a problem when the Silverlight toolkit's ContextMenu is clicked while it is over a UIElement that has registered a Tap event GestureListener. The context menu click propagates to the underlying element and fires its tap event.
For instance, say I have a ListBox and each ListBoxItem within it has registered both a ContextMenu and a Tap GestureListener. Assume that clicking context menu item2 is supposed to take you to Page1.xaml, while tapping on any of ListBox items themselves is supposed to take you to Page2.xaml.
If I open the context menu on item1 in the ListBox, then context menu item2 is on top of ListBox item2. When I click on context menu item2 I get weird behavior where the app navigates to Page1.xaml and then immediately to Page2.xaml because the click event also triggered the Tap gesture for ListBox item2.
I've verified in the debugger that it is always the context menu that receives the click event first. How do I cancel the context menu item click's routed event propagation so it doesn't reach ListBox item2?
Thanks for your help!
You can get around the problem by doing the following:
In the context menu's Opened handler set LayoutRoot.IsHitTestVisible (LayoutRoot is the default name for the root UIElement) to false
In the context menu's Closed handler set LayoutRoot.IsHitTestVisible back to true
You could try adding a rectangle with a transparent background (important) over the effected area/page when showing the context menu.
I had a very similar issue, but I am using the ManipulationCompleted event as a "tap" detector as the object the ContentMenu applies to is a custom control.
LayoutRoot.IsHitTestVisible didn't work for me, perhaps because it does not apply to Manipulation events. However, it set me on the right path. I just implemented my own simple equivalent of it - I created a boolean variable bCancelManipulation in the page's scope.
In the ContentMenu's Opened event set it to True.
In the ContentMenu's Closed event set it to False.
In the ManipulationCompleted function, the first thing I do is check
if(bCancelManipulation==true) { return; }
It's kind of a hack, but it works great and is quite simple to code - it can easily be adapted to a Tap event too.

Disable MenuStrip Dropdown in Windows Forms Application

I am disabling the parent menu option in a Windows forms menustrip. When you hover over it, the submenu still opens. Is there a way to disable the submenu opening or do I have to disable all the submenu items?
Having the menu drop down show on mouse hover does not seem to be the default behavior of a ToolStripMenuItem and I could not find a property to enable this.
I did find this post by someone who wanted this behavior, and you should check to see if there is a MouseHover event handler for the ToolStripMenuItem and check the Enabled property there:
private void toolStripMenuItem1_MouseHover(object sender, EventArgs e)
{
if (toolStripMenuItem1.Enabled)
toolStripMenuItem1.DropDown.Show(menuStrip1, new Point(0, 0));
}
HTH
Just set the Enableproperty on the parent menu to False. In .net 2.0 and 3.5 the submenu will not show.
Also please try to be a little more specific.
I ended up looping through the DropDownItems and disabling them after I disable the main item.
for (int i = 0; i < this._menuOpen.DropDownItems.Count; i++)
{
this.menuOpen.DropDownItems[i].Enabled = false;
}

Popup window and context menu

I am using the ToolStripDropDown to host the user control as the pop-up window. The problem is when a context menu strip is displayed from within this pop-up window, the pop-up itself closes in the moment the context menu opens.
I have tried to subclass the ContextMenuStrip and added WS_EX_NOACTIVATE to CreateParams but nothing changed. First I thought that there is no way to do this since it is common behavior but then I tried to put a TextBox class onto the pop-up user control and invoke the Edit control context menu - and the parent pop-up window did not close.
What am I missing?
Had a similary Problem. On my UserControll was a toolstrip. When I pressed the toolsstripdropdownbutton the dropdown was shown but the popup disapeared.
The reason was that popup.Autoclose was true. After Setting to false the Popup is not closed any more.
ToolStripDropDown popup = new ToolStripDropDown();
popup.AutoClose = false; //Set to FALSE
popup.Margin = Padding.Empty;
popup.Padding = Padding.Empty;
ToolStripControlHost host = new ToolStripControlHost(userControl1);
host.Margin = Padding.Empty;
host.Padding = Padding.Empty;
popup.Items.Add(host);
popup.Show(button1, new Point(100,100));
Actual Solution should be the one in Martin's final comment:
Use ContextMenu Instead of ContextMenuStrip
That one worked for me, and the ToolStripDropDown no longer closes by itself when right clicking one of its content controls, like it should. We still need it to AutoClose, disabling AutoClose on ToolStripDropDown will do bad things, it is supposed to close on losing focus. Example: open any other app window, and the ToolStripDropDown will continue to appear on top

Resources