Trigger action method on Viewmodel on menuitem click

Topics: Actions & Coroutines, Conventions
Jan 24, 2012 at 2:59 PM

I Have a list of menu items bounded using convention

            <MenuItem Header="S_ettings">
                <MenuItem x:Name="Plugins" Header="Plugins">                    
                </MenuItem>
            </MenuItem>

I then have this collection on model

        public BindableCollection<PluginMenuViewModel> Plugins { get; set; }

How can i configure so that a Action method is triggered on the PluginMenuViewModel when menu item is clicked?

 

Thansk

Jan 24, 2012 at 4:19 PM

You use the cal:Message.Attach

<MenuItem Header="S_ettings">
                <MenuItem x:Name="Plugins" Header="Plugins"  cal:Message.Attach="MethodName($dataContext)">                    
                </MenuItem>
            </MenuItem>

cal is defined as
 xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"

HTH
Jan 24, 2012 at 9:06 PM

Thanks for reply! It kind of works, the method is triggered when clicking on the child menu, BUT $dataContext is the parent ViewModel,MainShellViewModel, not the menu item viewmodel, so there is no way for me to know which item was clicked :D

Im sure there is a solution to that? Thanks again!

Jan 25, 2012 at 7:45 AM

There must be a clean way of doing this right?

Jan 25, 2012 at 9:58 AM
Edited Jan 25, 2012 at 9:59 AM

This works, but its ugly because my Model has knowledge of the View now, I need a more elegant way :/

 

            <MenuItem Header="S_ettings">
                <MenuItem x:Name="Plugins" Header="Plugins" cal:Message.Attach="ShowSettings($eventArgs)">
                </MenuItem>
            </MenuItem>
        public IEnumerable<IResult> ShowSettings(RoutedEventArgs e)
        {
            var selectedPlugin = (e.OriginalSource as MenuItem).DataContext as PluginMenuViewModel;

            var pluginSettingsModel = new PluginSettingsViewModel(selectedPlugin.Plugin);

            yield return Result.ShowDialogResult(pluginSettingsModel);
        }
Coordinator
Jan 25, 2012 at 2:29 PM

Can you create a simple solution that reproduces the issue. I think I know what's going on, but I don't want to send you on a wild goose chase. If you can send it to me, I can advise better.

Jan 25, 2012 at 8:09 PM
EisenbergEffect wrote:

Can you create a simple solution that reproduces the issue. I think I know what's going on, but I don't want to send you on a wild goose chase. If you can send it to me, I can advise better.

Thanks for input Rob.

Heres a sample, its very close to the actual project

http://dl.dropbox.com/u/33026505/Caliburn.Micro.MenuSample.rar

Thanks, Anders

Jan 27, 2012 at 9:17 AM

Hi Rob, Have you had time to look at the example?

 

Thanks, Anders

Coordinator
Jan 27, 2012 at 4:46 PM

Sorry...not yet. I'll get to it...hopefully this afternoon.

Coordinator
Jan 27, 2012 at 8:28 PM

I'm going to teach you a special magic trick ;)

You can extend the list of special parameters recognized by the action message mechanism. Here's what you need to do:

Add the following code to you Bootstrapper's configure method:

MessageBinder.SpecialValues.Add("$orignalsourcecontext", context => {
    var args = context.EventArgs as RoutedEventArgs;
    if(args == null) {
        return null;
    }

    var fe = args.OriginalSource as FrameworkElement;
    if(fe == null) {
        return null;
    }

    return fe.DataContext;
});

Then change your MenuItem's action to this:

cal:Message.Attach="ShowSettings($orignalsourcecontext)"

That should do it. Does it make sense what is happening here?

Jan 29, 2012 at 12:56 PM

Thanks, worked like a charm.. yeah, its actually pretty close to what I did in the Action method. Much nicer to abstract it to the Caliburn bootstraper.. Thanks