WPF Menu/MenuItem MouseOver prevents click on window - c#

I have a simple window with a menu containing items bound to view models.
<DockPanel>
<Menu DockPanel.Dock="Top" ItemsSource="{Binding ViewModels}">
<Menu.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding HeaderName}" Visibility="{Binding MenuVisibility}"
Command="{Binding DataContext.ChangeViewCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding }"/>
</DataTemplate>
</Menu.ItemTemplate>
</Menu>
<Viewbox Stretch="Fill">
<ContentControl Content="{Binding CurrentViewModel}"/>
</Viewbox>
</DockPanel>
Everything for the Menu's style is default plane jane. Nothing fancy. No modifications.
I'm noticing some odd hover behavior when testing the UI. If I mouse over one of the menu items and it becomes highlighted, it seems to 'trap' focus on that item even if the mouse leaves.
So lets says I'm mousing UP through my application, my mouse cursor passes over the menu, highlighting an item. My mouse never stops and attempts to click the Window bar to move the UI to another monitor, the click never lands on the menu bar. I have to click twice, once to remove focus from the menu item, and again to select and drag the window. This also prevents clicks on the minimize, maximize and close buttons as well, or any focus back inside the form. It seems that the MenuItem does not properly notice the mouse has left.
Any ideas? I've tried gutting the Menu and MenuItem styles and have had no success. I've changed the DataTemplate to contain a Grid and used Interactions to trigger the commands, but its ugly and seems hacky.

Related

How do I prevent a ToolBar in a nested UserControl from being focused when switching tabs?

I wrote an example application that highlights the issue, which might have to do with focus-scope because it's whenever a ToolBar is involved and a UserControl is unloaded when switching tabs.
The main window contains a Menu with a File->New command and a TabControl that displays a collection of "Box" instances:
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<MenuItem Command="New"/>
</MenuItem>
</Menu>
<TabControl ItemsSource="{Binding Boxes}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" Width="40"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<local:BoxView/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</DockPanel>
Each "Box" instance has a Name property displayed in the tab header, and the rest of it is displayed in a "BoxView" UserControl. The "BoxView" has a ToolBar, the first button of which becomes the focus hog in the mentioned use case. The "BoxView" also displays a collection of "Compartments" that are inside each "Box" instance:
<StackPanel>
<ToolBarTray IsLocked="True">
<ToolBar>
<Button Content="Focus hog"/>
</ToolBar>
</ToolBarTray>
<ItemsControl ItemsSource="{Binding Compartments}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:CompartmentView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
Each "Compartment" instance has a TotalValue property simply displayed in a TextBox in a "CompartmentView" UserControl:
<StackPanel>
<TextBox Text="{Binding TotalValue}"/>
</StackPanel>
And the problem is...
If I click on the TextBox of any one of the CompartmentView's, and then click a different tab of the main window, the first button of the ToolBar of the BoxView is focused (the focus hog one), disabling commands working in the main window.
It can be observed commands are disabled when opening the File menu. But after closing the menu and reopening, commands are enabled again.
How do I prevent the ToolBar in the nested UserControl from being focused when switching tabs?
Or perhaps I'm going at this wrong... how do I prevent focus from being set when switching tabs?
Update
The following link is a video on youtube where I explain the problem with the application.
https://youtu.be/0T5LK3CYxgw
Solution update
Thanks to themightylc for the answer, the issue was clearly a keyboard focus problem when the focused visual control (any selected "CompartmentView" or "BoxView" control) was unloaded while changing the selected tab in the TabControl. The solution was to focus on the TabControl itself in the main window whenever the tab selection changed:
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
(sender as TabControl).Focus();
}
Thanks also to Christoph Nahr's response for the solution on this msdn thread: https://social.msdn.microsoft.com/Forums/vstudio/en-US/f5de6ffc-fa03-4f08-87e9-77bbad752033/a-focusscope-nightmare-bug-commands-are-disabled?forum=wpf
<Button Content="Focus hog" Focusable="False" />
This solves the problem you're having. Focusable is a DependencyProperty If you still want to access the ToolBar via Keyboard-Focus, you can bind it or set it from code-behind when the Tab-Switch is complete.
You can of course set it via Style so you don't have to set it on every element of the ToolBar.

WPF Button does not show ToolTip when TapAndHold consecutively

I'm implementing a .NET 4.5 WPF application on a touchscreen desktop. When testing my application, I realised that the tooltips for my buttons will not appear when I tap and hold the same button twice consecutively.
1) I tap and hold on Button A once, the tooltip for Button A appears as expected.
2) I tap and hold on Button A again (after the initial tooltip has disappeared), the tooltip will not appear again.
3) I tap and hold on Button B, tooltip for Button B appears.
4) I tap and hold on Button A now, tooltip for Button A now able to appear.
I am not sure whether this is the default behavior or it's something I did somewhere in my code that caused this to happen. Is there anything I can do to ensure the tooltip appears everytime?
Thanks for the help.
</StackPanel.Resources>
<ContentControl HorizontalAlignment="Center" VerticalAlignment="Center" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<MvvmLight:EventToCommand Command="{Binding MessageInfoVm.ShowInfoMessageCommand}" CommandParameter="{Binding ToolTipOk}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Button ToolTipService.ShowOnDisabled="True" ToolTip="{Binding ToolTipOk}" Command="{Binding OkCommand}" />
</ContentControl>
Try ToolTipService.ShowOnDisabled="True"
or additional event for MouseLeftButtonDown

Placing a Context Menu relative to button

I'm trying to do exactly what is described here, except with a Rectangle instead of a Button. I did what is described in the answer (among many other things), and I cannot get it to display as shown relative to the rectangle (which, in my case is being used by a button).
I am using a rectangle as a button because I didn't like the mouseover effects of a button and it seemed easier to just use a rectangle rather than building a custom button. As a note, I had this same problem even when I was using a button, in Expression Blend 4.
This is the XAML for my rectangle:
<Rectangle x:Name="rectangle" HorizontalAlignment="Left" MouseDown="MenuClicked" Height="55" VerticalAlignment="Top" Width="135" Grid.ColumnSpan="2" Margin="0,1,0,0" ContextMenuService.Placement="Bottom">
<Rectangle.ContextMenu>
<ContextMenu x:Name="Menu" >
<MenuItem x:Name="LoadXML" Header="Load XML" Command="{Binding Command}" CommandParameter="BrowseXML"/>
<MenuItem x:Name="SaveXML" Header="Save XML" Command="{Binding Command}" CommandParameter="SaveXML"/>
<MenuItem x:Name="SaveBinary" Header="Save Binary" Command="{Binding Command}" CommandParameter="SaveBinary"/>
<MenuItem x:Name="SaveText" Header="Save Text" Command="{Binding Command}" CommandParameter="SaveText"/>
</ContextMenu>
</Rectangle.ContextMenu>
<Rectangle.Fill>
<ImageBrush ImageSource="Resources/Logo.png" Stretch="Uniform" />
</Rectangle.Fill>
</Rectangle>
This still displays the contextmenu directly next to the point of mouse click. If I set Placement to bottom within the Context Menu code, rather than adding the ContextMenuService bit to the Rectangle, it displays it at the bottom or top relative to the entire window.
Any help would be appreciated. Thanks!
EDIT: I am also using a method to enable left-clicking of the rectangle. On MouseDown, it calls this method:
private void MenuClicked(object sender, System.Windows.RoutedEventArgs e)
{
Menu.PlacementTarget = this;
Menu.IsOpen = true;
}
You need to set the ContextMenuService.PlacementTarget property so the framework knows which element the context menu should be positioned relative to, e.g.:
<Rectangle x:Name="rectangle" ContextMenuService.PlacementTarget="{Binding RelativeSource={RelativeSource Self}}" ... />
Just add that property to your Rectangle declaration. When combined with ContextMenuService.Placement="Bottom", the context menu will appear at the bottom as you intended.
EDIT: Since you are opening the menu programatically, you need to set the Placement and PlacementTarget properties directly on the menu itself. The attached properties from ContextMenuService, when set on the menu's owner, will only take effect if the context menu is opened by conventional means, e.g., a right click. In your MouseDown handler, you are setting PlacementTarget = this;, but you should be setting PlacementTarget = rectangle;.

Disabled menu element in WPF looks enabled

My problem is twofold, but i guess that they are related, and if I manage to fix one of them, I will solve both.
First of, lets see the xaml code for a ContextMenu that is linked to a Caliburn.Micro view model:
<ContextMenu>
<MenuItem Header="Configure modem" ItemsSource="{Binding Modems}">
<MenuItem.ItemTemplate>
<DataTemplate>
<MenuItem>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ca:ActionMessage MethodName="SelectModem">
<ca:Parameter Value="{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</ca:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
<MenuItem.Header>
<DockPanel>
<Image DockPanel.Dock="Left" Source="{Binding CarrierProfile.CarrierProfileIcon}" Width="40" Height="40"/>
<TextBlock Text="{Binding MenuText}" VerticalAlignment="Center" Margin="10 0"/>
</DockPanel>
</MenuItem.Header>
</MenuItem>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</ContextMenu>
So basically this is just a DataTemplate where I set the Header to a DockPanel containing an image and a TextBlock.
One MenuItem looks like this:
Here you can see the main problem. You can see that there are "two selections". One outer selection, and one inner. If I click the inner selection, everything is fine, and my SelectModem method is called from my view model. However, if you click the outer selection the context menu goes away so that user thinks he has made a selection, but actually no method is called on the view model.
My second problem is that if I disable the MenuItem by adding IsEnabled="False" in the code above, the menu item looks disabled (text is grayed out), I cannot make the inner selection, but on hover is still shows the outer selection, and when clicked the menu goes away (but nothing is triggered in my view model)
So the question is: How can I get rid of the the outer selection?

wpf menu tab stop strange behaviour

I've just been cleaning up my program and I was checking how the tabs worked when I came across this very strange behaviour. My Main menu items were included in the tab order. Thinking that was strange I set their IsTabStop property to false, and ran it again.
They were no longer in my tab order but when I pressed ALT to activate the menu I could no longer use the arrow keys to navigate between the items.
Is there a way around this and make the menu act like a normal old school menu?
Here's how to exclude your menus from the tab order using KeyboardNavigation.TabNavigation:
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<MenuItem Header="Open"/>
<MenuItem Header="E_xit"/>
</MenuItem>
</Menu>
<StackPanel KeyboardNavigation.TabNavigation="Cycle">
<TextBox Text=""/>
<TextBox Text=""/>
</StackPanel>
</DockPanel>

Categories