Brutus
Brutus

Reputation: 790

Caliburn Micro Action inside ItemContainerStyle - No target found for method

I'm working on a WPF project using Caliburn Micro as a framework for MVVM, and during the last week I've been lucky enough to find every solution to any problem on StackOverflow, but now I'm facing a bigger issue that I can't solve by myself.

I have a View containing a TreeView; each item of the treeview should invoke a method when:

This is the TreeView:

<TreeView x:Name="projectTreeView"
              Visibility="{Binding ExplorerVisibility, Converter={StaticResource visibilityConverter}}">
        <TreeViewItem Header="{Binding ProjectName}" IsExpanded="True">
            <TreeViewItem Header="Category 1"/>
            <TreeViewItem Header="Category 2" ItemsSource="{Binding Images}">
                <TreeViewItem.ItemContainerStyle>
                    <Style TargetType="TreeViewItem">
                        <Setter Property="ContextMenu">
                            <Setter.Value>
                                <ContextMenu>
                                    <MenuItem Header="Remove"
                                              cal:Action.TargetWithoutContext="{Binding Path=DataContext, ElementName=projectTreeView}"
                                              cal:Message.Attach="[Event Click] = [Action RemoveResource()]"/>
                                </ContextMenu>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </TreeViewItem.ItemContainerStyle>
                <TreeViewItem.ItemTemplate>
                    <HierarchicalDataTemplate>
                        <HierarchicalDataTemplate.ItemContainerStyle>
                            <Style TargetType="TreeViewItem">
                                <Setter Property="IsExpanded" Value="True" />
                                <Style.Triggers>
                                    <EventTrigger RoutedEvent="Collapsed">
                                        <EventTrigger.Actions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <BooleanAnimationUsingKeyFrames 
                                    Duration="0" 
                                    Storyboard.TargetProperty="(TreeViewItem.IsExpanded)">
                                                        <DiscreteBooleanKeyFrame KeyTime="0" Value="True" />
                                                    </BooleanAnimationUsingKeyFrames>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </EventTrigger.Actions>
                                    </EventTrigger>
                                </Style.Triggers>
                            </Style>
                        </HierarchicalDataTemplate.ItemContainerStyle>
                        <ContentControl cal:Action.TargetWithoutContext="{Binding Path=DataContext, ElementName=projectTreeView}"
                                        cal:Message.Attach="[Event MouseDoubleClick] = [Action OpenResource(projectTreeView.SelectedItem)]">
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding ResourceName}" Margin="5,0,0,0"/>
                            </StackPanel>
                        </ContentControl>

                        <HierarchicalDataTemplate.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding}"/>
                            </DataTemplate>
                        </HierarchicalDataTemplate.ItemTemplate>

                    </HierarchicalDataTemplate>
                </TreeViewItem.ItemTemplate>
            </TreeViewItem>
        </TreeViewItem>
    </TreeView>

The attached ViewModel contains both methods:

public class MyViewModel
{
    ...

    public void OpenResource(object obj) { ... }

    public void RemoveResource() { ... }

}

For some reason OpenResource works perfectly, while when I click on the context menu item (after right click) the application crashes with the exception:

An unhandled exception of type 'System.Exception' occurred in WindowsBase.dll

Additional information: No target found for method RemoveResource.

I found something related to the same problem here on the forum and on the support forum, but I was not able to fix the problem with those tips.

Do you have any idea about what's going on in my TreeView?

Thank you very much for the help!

Upvotes: 1

Views: 1499

Answers (1)

mm8
mm8

Reputation: 169190

The ContextMenu resides in its own visual tree and can't bind to the TreeView using an ElementName.

You could try to bind the Tag property of the TreeViewItem to the parent TreeView and then bind to it using the PlacementTarget property of the ContextMenu:

<Style TargetType="TreeViewItem">
    <Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=TreeView}}" />
    <Setter Property="ContextMenu">
        <Setter.Value>
            <ContextMenu>
                <MenuItem Header="Remove"
                                  cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag.DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"
                                  cal:Message.Attach="[Event Click] = [Action RemoveResource()]"/>
            </ContextMenu>
        </Setter.Value>
    </Setter>
</Style>

Upvotes: 3

Related Questions