Junior222
Junior222

Reputation: 833

WPF binding command to ContextMenu

I have a problem with command binding in WPF. I have the following xaml:

<ItemsControl ItemsSource="{Binding Entity}" Name="Lst">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>                    
                <Button  Content="qwerty" Command="{Binding ElementName=Lst, Path=DataContext.SaveCommand}" >
                    <Button.ContextMenu>
                        <ContextMenu>                                
                            <MenuItem Header="Send2" Command="{Binding ElementName=Lst, Path=DataContext.SaveCommand}" />
                        </ContextMenu>
                    </Button.ContextMenu>    
                </Button>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

As you can see Button and its ContextMenu have the similar command-bindings. But when i click button its command is firing and when i click context menu's item its command isn't firing. Where am i wrong? Thanks in advance!

Upvotes: 1

Views: 6148

Answers (2)

Krishna
Krishna

Reputation: 1996

I had a similar problem before and solved it by passing the datacontext through the tag property of the container as below. I have it working on a grid ContextMenu but dont see any reason why this wont work on a button. Let me know if you have any problem

<Button  Content="qwerty" Tag="{Binding DataContext,ElementName=Lst}" Command="{Binding ElementName=Lst, Path=DataContext.SaveCommand}"  >
                    <Button.ContextMenu>
                        <ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">                                
                            <MenuItem Header="Send2" Command="{Binding SaveCommand}" />
                        </ContextMenu>
                    </Button.ContextMenu>    
                </Button>

Upvotes: 5

Damascus
Damascus

Reputation: 6651

The ContextMenu being separate from the visual tree, you cannot bind with and element outside of it.

If you check your output window, you should have a message saying that it can't find the object "Lst"

A common and easy workaround would be to manually set the DataContext in code-behind (note: this is not breaking MVVM at all. You are just performing a pure UI operation of linking DataContexts together):

In your Xaml:

<Button.ContextMenu>
                        <ContextMenu Opened="OnContextMenuOpened">                                
                            <MenuItem Header="Send2" Command="{Binding ElementName=Lst, Path=DataContext.SaveCommand}" />
                        </ContextMenu>
                    </Button.ContextMenu>

In code-behind:

public void OnContextMenuOpened(object sender, RoutedEventArgs args)
{
    (sender as ContextMenu).DataContext = Lst.DataContext;
}

You are therefore linking the DataContext every time the ContextMenu is opened (so if Lst's DataContext changes, your ContextMenu will as well)

Alternatively (cleaner if you are bound to use it a lot of times), get the BindingProxy from this article: http://tomlev2.wordpress.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/ and it'll do the trick!

Upvotes: 1

Related Questions