Search code examples
wpfxamlmvvmdata-bindingcontextmenu

How to set DataContext of Button.ContextMenu same as the Button?


<Button Content="{Binding Type}" Name="Ellipsis" Tag="{Binding ElementName=Ellipsis, Path=DataContext}">
    <Button.ContextMenu>
          <ContextMenu x:Name="MainContextMenu" DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
              <MenuItem Header="{Binding Type}"/>
          </ContextMenu>
    </Button.ContextMenu>
    <Button.Triggers>
          <EventTrigger SourceName="Ellipsis" RoutedEvent="Button.Click">
              <BeginStoryboard>
                  <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MainContextMenu" Storyboard.TargetProperty="(ContextMenu.IsOpen)">
                         <DiscreteObjectKeyFrame KeyTime="0:0:0">
                             <DiscreteObjectKeyFrame.Value>
                                 <sys:Boolean>True</sys:Boolean>
                             </DiscreteObjectKeyFrame.Value>
                         </DiscreteObjectKeyFrame>
                      </ObjectAnimationUsingKeyFrames>
                  </Storyboard>
              </BeginStoryboard>
          </EventTrigger>
     </Button.Triggers>
</Button>

As shown above, Button.Content="{Binding Type}" works perfectly but when it goes in its ContextMenu, the DataContext changes which causing MenuItem Header="{Binding Type}" to not work. I researched online and someone said saving the outer DataContext in a tag and use it as the inner DataContext. I tried that in my code but ContextMenu still not reading the correct DataContext. The MenuItem Header should be the same as the Button.Content in this case but it is not. What should I do?


Solution

  • <Button Content="{Binding Type}" x:Name="EllipsisButton">
        <Button.ContextMenu>
              <ContextMenu x:Name="MainContextMenu">
                  <MenuItem Header="{Binding DataContext.Type,ElementName=EllipsisButton}"/>
              </ContextMenu>
        </Button.ContextMenu>
    </Button>
    

    One solution I have is to use ElementName. You can refer to an upper level with its x:Name. In this case, I am binding to Type from whichever component that has x:Name="EllipsisButton"