简体   繁体   中英

WPF Context menu on TabControl header

I have a TabControl and have bound its ItemSource to a ObserverableCollection of view models. I have also set its DataTemplate to the view assioated with the view model.

This works fine and in ItemContainerStyle I added a ContextMenu that have a MenuItem . How do I get the MenuItems click event to fire in my code? I am not able to pick up the event in Delete_OnClick . Also the sender should be a reference to the view model that is bound to the ItemSource of the TabControl .

    <TabControl ItemsSource="{Binding MyTabItems}">

        <TabControl.Resources>
            <DataTemplate DataType="{x:Type viewModels:MyTabItemViewModel}">
                <views:MyTabItem/>
            </DataTemplate>
        </TabControl.Resources>

        <TabControl.ItemContainerStyle>
            <Style TargetType="{x:Type TabItem}">
                <Setter Property="Header" Value="{Binding Path=Header}"/>
                <Setter Property="ContextMenu">
                    <Setter.Value>
                        <ContextMenu>
                            <MenuItem Header="Delete" Click="Delete_OnClick"/>
                        </ContextMenu>
                    </Setter.Value>
                </Setter>
            </Style>
        </TabControl.ItemContainerStyle>

    </TabControl>


    // In code behind I have this method that should be triggered when the
    // Delete MenuItem is clicked
    private void Delete_OnClick(object sender, RoutedEventArgs e)
    {
        var tabItem = (ITabItem) sender;
        ViewModel.DeleteTab(tabItem);
    }

Summary: I can right click on the tab header and click on Delete but I do not get any events from that.

I changed my original answer considerably.

My understanding is that you use MVVM pattern. If so you shouldn't use event handlers directly. Instead you should bind a menu item to a command.

<ContextMenu>
    <MenuItem Header="Delete" Command={Binding MyCommand} />
</ContextMenu>

MyCommand should be a property defined in your MyTabItemViewModel class.

public class MyTabItemViewModel 
{
    public ICommand MyCommand { get; set; }
    ...
}

MyCommand property can return an instance of any class that implements ICommand interface. It can be a predefined command (for example see ApplicationCommands class) or your own. Here is an example how your DeleteCommand could look like:

public class DeleteCommand: ICommand
{
    private ParentVM Parent { get; set; }
    private MyTabItemViewModel Item { get; set; }

    public MyCustomCommand (ParentVM parent, MyTabItemViewModel item)
    {
        Parent= parent;
        Item = item;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        parent.RemoveItem(item);
    }

    ...
}

I assumed that your view model with the MyTabItems collection is called ParentVM and that it has a public method RemoveItem which is responsible for removing a given item from this collection.

You can instantiate DeleteCommand in the constructor of MyTabItemViewModel . For example:

public class MyTabItemViewModel 
{
    public ICommand MyCommand { get; set; }

    public MyTabItemViewModel(ParentVM parent)
    {
        MyCommand = new DeleteCommand(parent, this);
    }

    ...
}

Use an EventSetter instead, that should work in your case

<Setter Property="ContextMenu">
                    <Setter.Value>
                        <ContextMenu>
                            <MenuItem Header="Delete" >
                                <MenuItem.Style>
                                    <Style TargetType="MenuItem">
                                        <EventSetter Event="Click" Handler="Delete_OnClick"/>
                                    </Style>
                                </MenuItem.Style>
                            </MenuItem>
                        </ContextMenu>
                    </Setter.Value>
                </Setter>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM