WPF ContextMenu = {x: Null}, but still shows the menu inside ContentControl

I need to disable the standard ContextMenu from a TextBox. I created a new WPF project and added the following:

<Window x:Class="WpfApplication3.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <ContentControl> <ContentControl.ContentTemplate> <DataTemplate> <TextBox ContextMenu="{x:Null}" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox> </DataTemplate> </ContentControl.ContentTemplate> </ContentControl> </Grid> </Window> 

But this is what I get:

enter image description here

The following code works fine:

 <Grid> <TextBox ContextMenu="{x:Null}" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox> </Grid> 

Why is this happening?

Refresh.

According to the accepted answer, I created a class derived from TextBox to show ContextMenu to parents.

  public class TextBoxNoMenu: TextBox { public TextBoxNoMenu() { ContextMenu = null; } } 
+7
c # wpf contextmenu contentcontrol
source share
4 answers

Why is this happening?

This is an interesting case of changing control behavior depending on where / how the property is set.

TextBox has its own context menu by default. The time only when this is not done is when you explicitly set the local ContextMenu value to null . This is what happens in your simple example where the TextBox is located directly inside the Grid .

However, when you set a property inside a template, you are not actually setting a local value; you set the value to the parent template. If you check the value using DependencyPropertyHelper.GetValueSource() , you will see that the source of the base value is ParentTemplate instead of Local . Thus, the menu is still overridden.

For more information, see Priority for a Dependency Property Value for more information on the various sources of dependency property values.

@OmegaMan suggests assigning a "hidden" context menu, it seems to work very well.

+3
source share

Note that although you can disable ContextMenu in a TextBox if it is in another control, you can see ContextMenu of such a shell. Try Snooping to see this behavior more accurately.

Note also that many default control templates in WPF can cause such problems by adding their own child objects. Seeing the default template for a TextBox uses Border and then <ScrollViewer Margin="0" x:Name="PART_ContentHost" /> , you probably see ContextMenu of the child if the TextBox.

+1
source share

This seems to be a problem when X: Null does not disable the context menu by default. A better way would be to change its visibility:

 <TextBox.ContextMenu> <ContextMenu Visibility="Collapsed"/> </TextBox.ContextMenu> 
+1
source share

I had a similar problem, but I generated my controls programmatically, and my parent control is a dock. Based on the accepted answer, I decided to set the value to zero in the code.

  <Grid> <DockPanel> <TextBox Name="txtBox" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox> </DockPanel> </Grid> 

and then

  private void Window_Loaded(object sender, RoutedEventArgs e) { txtBox.ContextMenu = null; } 

EDIT: I felt this was a kind of random answer, as it does not completely or directly solve this issue. I did something, and if you implement the method found in the answer to this question , you can find the text field in the code.

So, if you have this

  <Grid> <ContentControl> <ContentControl.ContentTemplate> <DataTemplate> <TextBox Name="txtBox" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox> </DataTemplate> </ContentControl.ContentTemplate> </ContentControl> </Grid> 

Then you can find your text field by name (txtBox in this case) and set the context menu to null

  TextBox myTextBox = FindChild<TextBox>(Application.Current.MainWindow, "txtBox"); myTextBox.ContextMenu = null; 

Personally, I would prefer this to create a new class with inheritance, but that's all that works for you. It still doesn't answer "Why is this happening?" but I think the accepted answer does a good job of this.

0
source share

All Articles