Question

I am trying to bind an auto-created menu item's command to an ICommand exposed by the parent MenuItem's ViewModel. The following is hopefully a good representation of what I have:

Custom Control:

class MyMenuItem : MenuItem {}

ViewModels:

class ParentVM
{
    public IEnumerable<ChildVM> Children { get; set; }
    public ICommand TheCommand { get; set; }
}

class ChildVM
{
    public string Name { get; set; }
}

Global style for custom control:

<Style TargetType="namespace:MyMenuItem">
    <Setter Property="Header" Value="Some Text"/>
    <Setter Property="ItemsSource" Value="{Binding Children}"/>
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="MenuItem"/>
                <Setter Property="Command" Value="{Binding [parent].TheCommand}"/>
                <Setter Property="Header" Value="{Binding Name}"/>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

Consuming in context menu:

<ContextMenu>
    <namespace:MyMenuItem DataContext="{Binding AParentVM}"/>
</ContextMenu>

I need to know what goes into the line with [parent]. Child menu items do get created and their name shows right, which tells me that I have the right DataContext at the top level because "Children" bound right, and I have the right DataContext at the bottom level because "Name" bound right. I expected a RelativeSource binding using an AncestorType of MyMenuItem would be what was needed, but it did not work.

Was it helpful?

Solution

<Setter Property="Command" Value="{Binding DataContext.TheCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type namespace:MyMenuItem}}}"/>

Alternatively, give the child VM a reference to the parent, or to the command that it needs to expose.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top