WPF context menu doesn't stay open - c#

In WPF I am trying to put a context menu on the items of a listbox. When I run my app and right click on an item of the listbox the menu pops up for a split second and then closes again. I just can't figure out what I am doing wrong.
This is the code I am using:
<ListBox Grid.Column="0" Name="lsbAddedElements" Width="150" Margin="3,3,3,3"
SelectionMode="Multiple">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Delete" Click="btnDeleteElement_Click"></MenuItem>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
The listbox is bound to an ObservableCollection in code when the window is initialised, so item management is taken care of in code behind.
UPDATE:
I might need to add that thsi is part of an adin I am making for Excel. I am connecting to Excel using ExcelDNA then passsing the handle on to the WPF window that this code snippet is part of.
Could this be a reason for the context menu behaving in an unexpected way?

I think the problem is that the listbox item is getting focused. A simple solution to your problem is to set the context menu on the list box and enable/disable context menu items if the list box has a selected item.

Related

Pass Variable from parent to child in a hybrid WPF MVVM-usercontrol schema

I have a program with the following schema.
The program starts with a login, once the user puts the name and password it directs to the main window (no problem passing the values there as it is between forms). This windows uses a MVVM schema to load the ContentControl necessary in that moment.
<Window.Resources>
<DataTemplate ...>
</DataTemplate> (several times)
</Window.Resources>
<DockPanel>
<Menu DockPanel.Dock="Top" ItemsSource="{Binding MenuItems}">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Command" Value="{Binding Command}" />
</Style>
</Menu.ItemContainerStyle>
<Menu.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=MenuItems}">
<TextBlock Text="{Binding Header}"/>
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
</Menu>
<ContentControl Content="{Binding CurrentPageViewModel}" >
</ContentControl>
</DockPanel>
As you can see from the code, it has a binded menu (which does not change) and a ContentControl, which calls a UserControl depending on what button has been pressed on the menu. The ContentControl is binded and uses a MVVM model to load the UserControl.
The problem is that the UserControl is not using a MVVM schema (only the loading part uses the MVVM). They are directly operating in c# using a direct WPF model (.cs and .xaml), so the UserControl ViewModel does not bind anything in the Model UserControl.
I want to find a way to pass the login information to the called UserControl. In a way that every time it changes the ContentControl, the new UserControl will have acces to the login data.
Is there any way to create a global-like variable that can be posted by the login or the main window, and read by each of the UserControls?
It is not exactly what i wanted but i did the trick by using the project properties.
I set it in the loggin and get it in the window i want.
object myProperty = App.Current.Properties["Test"];

Hide items in a ListBox when ListBox is disabled

When a standard ListBox is disabled, the elements in it are simply grayed out. They are still visible, despite not being clickable. I would like to know if it is possible, and if it is, how to hide these items when the ListBox is disabled. I do not want to remove the elements from the ItemSource or create a temp storage for them.
So far, I thought about changing the visibility of the ListBox but that gets rid of the entire thing (including the border lines).
You could bind Visibility of ListBoxItem to IsEnabled of ListBox
<ListBox ItemsSource="{Binding DataSource}">
<ListBox.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</ListBox.Resources>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Visibility" Value="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource BooleanToVisibilityConverter}}" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Just add another ListBox to the form and when you disable the first listbox with the elements inside of it, hide it, and then display the other to the user which will essentially be an empty greyed out listbox.
Then when you enable the box back, hide the empty one and show the real one.
Hope this helps.

How can I apply a custom TextBox style to built-in controls?

Background:
In a standard WPF application, right clicking on a TextBox displays a ContextMenu with three commands: Cut, Copy, and Paste. My desire is to add a Select All command to all TextBox ContextMenus in my application.
Problem:
My standard approach is to create a Style that targets TextBox and supplies the new ContextMenu. That way, all TextBox controls inherit the style and pick up the change.
The trouble is that my style isn't inherited by controls that contain TextBoxes. For instance, when editing a DataGridTextColumn cell, I know a TextBox is used but it doesn't inherit my style. The same goes for some 3rd party controls used by my application.
Question:
Is there some other way to have controls, like the DataGridTextColumn's cell, pick up my style changes, or am I stuck altering their templates?
Addendum:
This is the style:
<Style
TargetType="{x:Type TextBox}"
BasedOn="{StaticResource {x:Type TextBox}}"
>
<Setter
Property="ContextMenu"
>
<Setter.Value>
<ContextMenu>
<MenuItem
Header="Cu_t"
Command="ApplicationCommands.Cut"
InputGestureText="Ctrl+X"
/>
<MenuItem
Header="_Copy"
Command="ApplicationCommands.Copy"
InputGestureText="Ctrl+C"
/>
<MenuItem
Header="_Paste"
Command="ApplicationCommands.Paste"
InputGestureText="Ctrl+V"
/>
<Separator
/>
<MenuItem
Header="Select _All"
Command="ApplicationCommands.SelectAll"
InputGestureText="Ctrl+A"
/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
your textbox style will be reflected to textboxes who dont have any style applied. So if you have any third party textbox and it has already a style applied with key. your style will fail. you may need to use expression blend to open the the control template and change style or understand how the textbox style applied there.
cheers..

Firing context menu from user control does not work

I try to use a context menu from a user control's list view but the command is not firing (neither enabling/disabling when needed).
Code:
<UserControl ....
<UserControl.Resources>
<ContextMenu x:Key="SharedInstanceContextMenu">
<MenuItem Header="Edit" Command="{Binding ElementName=UC, Path=DataContext.EditSelectedItemCommand}" CommandParameter="{Binding}"/>
</ContextMenu>
<Grid ...>
<ListView ....>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected}"/>
<Setter Property="ContextMenu" Value="{StaticResource SharedInstanceContextMenu}"/>
</Style>
</ListView.ItemContainerStyle>
How can I make the command firing (and enabling/disabling, part of the command behavior)?
(btw, this questions seems similar to Treeview context menu command not firing but after trying all solutions there it still does not work.)
Does your output window contain binding errors complaining the command doesn't exist on your view model? If so, it probably means that your ContextMenu's DataContext isn't set correctly. Context menus are not part of the visual tree because they need to pop up on top of elements which means they don't inherit their DataContext the way other controls do. One solution is to use the PlacementTarget to access your view model - see this post for more information.

WPF: How to open a ContextMenu from all areas of a Grid control

I'm trying to add a ContextMenu to items in a ListBox in WPF;
<ListBox.ItemTemplate>
<DataTemplate>
<Border>
<Grid>
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header = "Menu item 1"/>
<MenuItem Header = "Menu item 2"/>
<MenuItem Header = "Menu item 3"/>
</ContextMenu>
</Grid.ContextMenu>
........
........
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
The problem is that the ContextMenu will only open when clicking on the actual context of the Grid, I want to be able to open the menu by clicking anywhere on the Listbox item.
Should I wrap the Grid in some other control?
It has been a several months since I've done any solid WPF development (was moved from application development to an actual game team).
From memory, you want to set the ContextMenu property on the Border and then set the Border.Background=Transparent. Setting the background to transparent ensures that it will be participate in the hit detection.
Alternative solution, would be ensure you Grid element stretches horizontally and vertically to fit the container.
...
Also pull the ContextMenu out as a static resource, so that is will be easier to find/edit in the future.
Hope this helps (and my memory does not fail me).
EDIT: I have answered a similar question on StackOverflow previously, please see my answer on WPF: Displaying a Context Menu for a GridView's Items. This answer is more complete as it sets the focus on the ListItem.
As you have already realized, - thanks to Dennis, - you have to set some background. Yes, transparent background is also OK:
<Grid Background="Transparent">
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header = "Menu item 1"/>
<MenuItem Header = "Menu item 2"/>
<MenuItem Header = "Menu item 3"/>
</ContextMenu>
</Grid.ContextMenu>
........
........
</Grid>
REFERENCE: https://blogs.msdn.microsoft.com/domgreen/2008/12/08/wpf-hit-testing-with-event-bubbling/

Categories

Resources