Search code examples
c#wpfevent-handlingclickcode-behind

Adding click event to generated MenuItems with datatemplate in WPF


I'm creating a menu dynamically based on a list of "BODPresentationRule" objects. While I can add them to the list, I can't find out how to add a click event to the (sub)MenuItems using the datatemplate.

When I use the PolygonShapesMenu_OnClick Click event from the First MenuItem I can see that there was a click, but not which subMenuItem it was.

XAML:

<Menu VerticalAlignment="Center" >
    <MenuItem Name="PolygonShapesMenu" Click="PolygonShapesMenu_OnClick">
        <MenuItem.Header>
            <StackPanel Orientation="Horizontal">
                <Image Source="/Assets/Images/polygon.png" Height="24" Width="24"></Image>
                <Label>Polygoon</Label>
            </StackPanel>
        </MenuItem.Header>
    </MenuItem>
</Menu>

The code behind (creating the menu) [note, due to the nature of the app, I'm not using MVVM (lots of drawing etc...]:

// create and set the datatemplate
DataTemplate polyDataTemplate = new DataTemplate(typeof (BODPresentationRule));
PolygonShapesMenu.ItemTemplate = polyDataTemplate;

// create and add the text box to the data template
var txtElement = new FrameworkElementFactory(typeof(TextBlock));
polyDataTemplate.VisualTree = txtElement;

// set the binding in the text box bound to the name of the BodPresentationRule
txtElement.SetBinding(TextBlock.TextProperty, new Binding("Name"));

// TODO: how to intercept click event to the current selected item?

// add items to menu
foreach (BODPresentationRule rule in _presentationRules.OrderBy(r=>r.Name))
{
    PolygonShapesMenu.Items.Add(rule);
}

FYI, it results in this:

example of menu

I was thinking about using Triggers to intercept a click event that would be added to the datatemplate, but I'm not even sure if that's the correct way to do it.

Summary: I need to know what BODPresentationRule (MenuItem) was clicked; how can I intercept the correct click event pointing to that rule.


Solution

  • You're only handling the click on the "header" MenuItem here. Put the click handler into a Style inside the MenuItem's ItemContainerStyle.

    <MenuItem>
        <MenuItem.ItemContainerStyle>
            <Style TargetType="{x:Type MenuItem}">
                <EventSetter Event="Click" Handler="PolygonShapesMenu_OnClick"/>
            </Style>
        </MenuItem.ItemContainerStyle>
    </MenuItem>
    

    The clicked sub MenuItem will then be the sender.