WPF MenuItem ItemsSource DataTemplate problem

Apr 28, 2011 at 8:00 PM


I have the following xaml that I'm trying to bind to my ViewModel to get sub menu items. This part seems to work and They show up in the menu.  The problem is the Message.Attach I'm trying to use to call SelectWidget passing in the name and the message I get says it can't find the target object that has SelectWidget

        <Menu HorizontalAlignment="Stretch">
                <MenuItem Header="Widget" ItemsSource="{Binding WidgetMenuSource}">
                        <DataTemplate DataType="{x:Type InstalledTypes:Widget}">
                            <MenuItem Header="{Binding Path=Name}" Micro:Message.Attach="SelectWidget($Header)"/>

I am assuming it is trying to find SelectWidget on the selected Widget item and not on my ViewModel but I can't figure out how to point it at my DataContext.

This works if I just hard code some MenuItems with the right names and use the same Message.Attach value.

Any ideas appreciated.

Apr 28, 2011 at 8:39 PM

Honestly, I think that the framework should navigate the Visual Tree to retrieve the proper VM to invoke the action method to.

My only guess is that, since you are indeed injecting a MenuItem inside another (the ItemContainer of a MenuItem is a MenuItem), something is going wrong and the proper VM is not identified.

Could you try to change your code to the following?

<Menu HorizontalAlignment="Stretch">
        <MenuItem Header="Widget"
                  ItemsSource="{Binding WidgetMenuSource}">
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Header" Value="{Binding Path=Name}"/>
                    <Setter Property="Micro:Message.Attach" Value="SelectWidget($Header)"/>

Otherwise, you could try specify to specify the Action.TargetWithoutContext in the MenuItem DataTemplate (or in a Setter in the above Style).

May 1, 2011 at 5:30 PM

Yeah, I thought this might be a case of it not being able to navigate the Visual Tree since they internally get wrapped in a different object.  Usually you can have get it back on track in a binding.  Is it possible to use a binding inside the parameter to SelectWidget?  Like SelectWidget({Binding Name, RelativePath=FindAncestor(WidgetView)})?

Right now I got it working by creating a WidgetMenuItem object that had a SelectWidget method on it and used a closure to call the VM's SelectWidget method and pass the Name.  But seems like a hack and something that shouldn't be necessary.

I'll try the ItemContainerStyle and see if that helps.


May 1, 2011 at 11:27 PM

Well, it is possible to use Binding using the long syntax (setting the trigger explicitly), or using the method described here.