I have a context menu to show up manually by pressing the hotkey ctrl+menu. Therefore i use this function:
ContextMenu.IsOpen = true;
I call this in my main window. But it has some odd effects.
If I only press the menu-key, the menu alwasy appears in the middle of the screen
If I manually call the menu, it always appears in the top left corner.
my menu is this one:
<Window.ContextMenu>
<ContextMenu Placement="Center">
<MenuItem IsCheckable="False" Name="item2" Click="MenuItem_Click" Header="{DynamicResource countDownNotificationOn}"/>
</ContextMenu>
</Window.ContextMenu>
using the xaml placement above dosen't work either. Therefore I set the window to
ContextMenuService.Placement="Center"
But doesn't work.
You need to set the PlacementTarget property of the ContextMenu:
if (element.ContextMenu != null )
{
element.ContextMenu.PlacementTarget = element;
element.ContextMenu.IsOpen = true;
}
If after this, the ContextMenu is still not placed correctly, you can set the placement using the ContextMenu.HorizontalOffset and ContextMenu.VerticalOffset properties. Take a look at the ContextMenu.HorizontalOffset Property and ContextMenu.VerticalOffset Property pages at MSDN for more information.
Related
I have a ListBox dynamically generated.
In this ListBox there are some Items that the user could select, one or more, by left click.
With the right click on an Item of the ListBox area he could show a context menu.
My problem is that if the user right-clicks in the ListBox area all goes right, but if he right-clicks on an Items he toggles the selection.
I want to avoid the Items toggling by the right click.
This is how I configured the ListBox in the MyWindow.cs:
MyBeautifulList.SelectionMode = SelectionMode.Extended;
And this is a portion of the relative XAML file:
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Send file" Click="SendFileToUser" />
<MenuItem Header="Send folder" Click="SendFolderToUser" />
<MenuItem Header="Copy user ID to the clipboard" Click="copyUserIDtoClipboard" />
</ContextMenu>
</ListBox.ContextMenu>
As well as click, wpf offers a bunch of other options.
Due to bubbling and tunnelling routed events which you might want to read up on.
You can handle the preview version of an event, mark it as handled and then it stops it firing.
void MenuItem_PreviewRightMouseButtonDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
You will then have no context menu appear, so you will need to show the context menu using code.
Name your context menu
<ContextMenu Name="SomeMeaningfulName">
You can then set IsOpen in code in your new handler, like:
SomeMeaningfulName.IsOpen = true;
I have a WPF ContextMenu instance declared in my XAML like this
<Window.ContextMenu>
<ContextMenu>
<MenuItem Header="Do Nothing"/>
<Separator/>
<MenuItem Header="{x:Static p:Resources.MenuExit}" Click="IconMenu_Exit"/>
</ContextMenu>
</Window.ContextMenu>
I'm using the WinForms NotifyIcon to display a tray icon like this
_notifyIcon = new System.Windows.Forms.NotifyIcon();
_notifyIcon.Icon = Properties.Resources.mainicon;
_notifyIcon.Visible = true;
_notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(OnTrayIconMouseClick);
The implementation of the mouse click handler is this
private void OnTrayIconMouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
ContextMenu.IsOpen = true;
}
}
This displays the context menu and clicking on the menu items dismisses it, but if I just click away on another window, the context menu stays visible. This seems like strange default behavior. Is there another way to display the context menu other than IsOpen or do I have to explicitly hide the context menu somehow?
Edit: I don't know if it matters but the window's DataContext is set to this in its code-behind.
Edit2: The context menu dismisses properly if it's invoked by right clicking on the actual main window but not from the tray icon.
Check that you have not defined the StaysOpen property as true.
I have a ContextMenu as part of a TabControl such as:
<TabControl Name="MyTabControl">
<TabControl.ContextMenu>
<ContextMenu Name="MyContextMenu" IsEnabled="False" StaysOpen="True">
<MenuItem Header="Item1"></MenuItem>
...
</ContextMenu>
</TabControl.ContextMenu>
</TabControl>
As you can see, the menu is disabled. It will be enabled later in the program, for now however, it should remain in its disabled state. The problem is, when I right-click the TabControl and the disabled menu shows, it simply stays where it was first opened, no other right-click will move it, nor will a left-click somewhere make it disappear.
The only way to get rid of it, would be either by enabling it and then right/left-clicking, or by using MyContextMenu.Visibility = Visibility.Collapsed/Hidden;
I tried setting the StaysOpen-property to False. Then the menu will open once in its disabled state. After left-clicking disappear and then not appear again even if it gets enabled.
The only way around it could be changing the StaysOpen-property along with the IsEnabled-property, but it is a bit weird that the menu opens exactly once in its disabled state and then not anymore.
I hope anybody could explain to me, why exactly a disabled menu won't close and the property StaysOpen at false makes it open exactly once, because it seems like a weird behaviour to me.
It seems that the behaviour of context menu items is quite strange - what you've described is in .Net 4.0 and if you target yor app to .Net 3.5 for instance you will notice the opposite behaviour - you can't make the menu stay opened if the single item is disabled, it just disappears immediately after it shows on right click.
However I think the preferrable way to manage the enabled state of a context menu item (and also the OnClick action it should do) is by a Command.
First you should specify a datacontext for your view, let's say it is the class ViewModel.cs. Then create a command by implementing the ICommand interface, something like this:
public class MyCommand : ICommand
And then you have a CanExecute method which does exactly what it's name says - decides if the command can be executed or not. And the enabled state of the menu item also depends on the return value of this method. So you can keep it returning false as long as you need in and the menu will behave correctly and the menu item will be disabled. Then when you want you can make it return true (by some logic in the method itself) and you'll have again a properly working context menu with enabled menu item.
If you want to disable the entire menu, use the same approach but for the menu.
And if you need to make all the items in the menu disabled (which I think is different from the entire menu), then you can use something like this:
<TabControl Name="MyTabControl" Background="Green">
<TabControl.ContextMenu>
<ContextMenu Name="MyContextMenu" StaysOpen="True" ItemsSource="{Binding Items}">
<ContextMenu.ItemTemplate>
<DataTemplate >
<MenuItem Header="{Binding Header}" IsEnabled="False" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</TabControl.ContextMenu>
</TabControl>
Here your ItemsSource (Items) is for instance List<MenuItem>, and MenuItem itselw would be your Model (thinking in MVVM) for each of your menu items, which should have property Header that contains the header you want to see in each menu item. Instead of setting the IsEnabled to false as in my dummy example, you can bind it to a property in order to have control on when it must be true and false.
I would like to control when the contextmenu of my control to show or not.
here is my code:
void MyControl_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if ( some condition .....)
{
this.Focus();
contextmeun.PlacementTarget = this;
contextmeun.IsOpen = true;
}
}
However, it just show up less than 1 second then disappear immediately. Why is that?
Thank you for all your help!
Probably because you're focussing the control that the context menu belongs to, then showing the context menu, however when the parent control gets focus, the context menu closes.
Try setting the context menu in Xaml instead to get the correct behaviour
<MyControl>
<MyControl.ContextMenu>
<ContextMenu>
<!-- Define context menu here -->
</ContextMenu>
</MyControl.ContextMenu>
</MyControl>
This can be done in pure XAML form, all you need to do is bind your visibility of context menu with a bool property containing your condition like this -
<YourControl>
<YourControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</YourControl.Resources>
<YourControl.ContextMenu>
<ContextMenu Visibility="{Binding IsEnable,
Converter={StaticResource BooleanToVisibilityConverter}}">
<MenuItem Header="MenuItem1"/>
<MenuItem Header="MenuItem2"/>
<MenuItem Header="MenuItem3"/>
</ContextMenu>
</YourControl.ContextMenu>
</YourControl>
Here IsEnable is a plain CLR property, in its getter you can have the logic for your condition depending on which you need to toggle the visibility of your context menu..
I want to change Menu's Text color, but not MenuItem.
You should be able if its Visual c# you should be able to right click the widget and adjust the foreground property. Foreground usually sets the text color in Visual .net widgets like Labels, buttons, textboxes, so I think it'll probably be there for menus.
In Xaml:
<Menu Foreground="Red">
<MenuItem Header="_File"></MenuItem>
</Menu>
Didn't see the menu item but not menu... The File will be blue Edit will be red.. You datatemplate to set your style depending on the menu item
<Menu Foreground="Red">
<MenuItem Foreground="Blue" Header="_File"></MenuItem>
<MenuItem Header="_Edit"></MenuItem>
</Menu>
In windows form application, in code behide of the form, in the constructor just after InitializeComponent(), set color property of the menu, like this:
MyMenu.ForeColor = Color.White;