views:

768

answers:

3

I've got a MenuItem whos ItemsSource is databound to a simple list of strings, its showing correctly, but I'm struggling to see how I can handle click events for them!

Here's a simple app that demonstrates it:

<Window x:Class="WPFDataBoundMenu.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
    <Menu>
        <MenuItem Header="File" Click="MenuItem_Click" />
        <MenuItem Header="My Items" ItemsSource="{Binding Path=MyMenuItems}" />
    </Menu>
</Grid>

using System.Collections.Generic;
using System.Windows;

namespace WPFDataBoundMenu
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public List<string> MyMenuItems { get; set;}

        public Window1()
        {
            InitializeComponent();
            MyMenuItems = new List<string> { "Item 1", "Item 2", "Item 3" };
            DataContext = this;
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("how do i handle the other clicks?!");
        }
    }
}

Many thanks!

Chris.

+3  A: 

You could have each menu item execute the same command, thus handling the execution centrally. If you need to distinguish menu items beyond the actual object instance, you can bind the command parameter too:

<MenuItem Header="My Items" ItemsSource="{Binding Path=MyMenuItems}">
    <MenuItem.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="Command" Value="{x:Static local:MyCommands.MyCommand}"/>
            <Setter Property="CommandParameter" Value="{Binding SomeProperty}"/>
        </Style>
    </MenuItem.ItemContainerStyle>
</MenuItem>

SomeProperty is assumed to be a property on each item in your MyMenuItems collection. Your command execution handler would therefore receive the value of SomeProperty for the particular menu item that is clicked.

HTH, Kent

Kent Boogaart
This would still lead to a central handler, which switches on the SomeProperty value. wouldn't it?
Gishu
Yeah, that's right. Actually, the parameter isn't mandatory. You could branch based on the MenuItem instance instead, but I've found there's often a piece of data specific to each menu item that is required. eg. consider recent file menu items. The important piece of info is the file path.
Kent Boogaart
+5  A: 
<MenuItem Header="My Items" ItemsSource="{Binding Path=MyMenuItems}" Click="DataBoundMenuItem_Click" />

Code behind..

private void DataBoundMenuItem_Click(object sender, RoutedEventArgs e)
{
   MenuItem obMenuItem = e.OriginalSource as MenuItem;
   MessageBox.Show( String.Format("{0} just said Hi!", obMenuItem.Header));
}

Events will bubble up to the common handler. You can then use the Header text or better the DataContext property to switch and act as needed

Gishu
A: 

Thanks for both your answers, they are both spot on, the first one actually answered my question as i wrote it, and since gishu got there first and it does indeed answer it, i guess i have to give the answer to him.

But kent, you must have been reading my mind, yours is actually what I was really after, and it was only after i posted it i realised that i should have included some more detail, i.e. the fact that i am using Commands with databinding.

Big thanks goes to you both!

Cheers, Chris.

Chris Browne
AFAIR Kent got in first.. maybe he should get the 'accepted' answer
Gishu
Ha, ha! Good of you Gishu but it's cool - as long as Chris has the answer.
Kent Boogaart