在DataTemplate中为MenuItem指定命令

时间:2009-05-22 16:49:29

标签: wpf datatemplate command

我有一个上下文菜单。它绑定到某个集合,它有一个定义的ItemTemplate,如下所示:

<ContextMenu
    ItemsSource={Binding ...}
    ItemTemplate={StaticResource itemTemplate}
    />

itemTemplate是一个带有TextBlock的简单DataTemplate:

<DataTemplate x:Key="itemTemplate">
    <TextBlock Text={Binding ...} />
</DataTemplate>

如何将MenuItem的Command属性绑定到底层对象的属性?

3 个答案:

答案 0 :(得分:24)

我认为你需要将TextBlock包装在MenuItem中:

<DataTemplate x:Key="itemTemplate">
    <MenuItem Command={Binding ...}>
        <TextBlock Text={Binding ...} />
    </MenuItem>
</DataTemplate>

但我现在没有在我面前试用这个IDE。让我知道它是怎么回事。


看起来您需要使用ItemContainerStyle,如here所示。很抱歉在开始的时候引导你走错了道路 - 但是我在IDE前面就可以了,这很有效:

<ContextMenu.ItemContainerStyle>
    <Style TargetType="MenuItem">
        <Setter Property="Command" Value="{Binding ...}"/>
    </Style>
</ContextMenu.ItemContainerStyle>

答案 1 :(得分:6)

虽然这只是Martin Harris的答案的一个微小变化,但我认为无论如何我都会分享它。我发现更有用的是为整个集合指定一个命令,并且还发送一个CommandParameter:

<MenuItem.ItemContainerStyle>
    <Style TargetType="MenuItem">
       <Setter Property="Command" Value="{x:Static v:ViewModel.CommandForAll}"/>
       <Setter Property="CommandParameter" Value="{Binding ValueForCommand}"/>
    </Style>
</MenuItem.ItemContainerStyle>

然后,您可以确定在命令的处理程序中执行的操作:

private void CommandForAll_Executed(object sender, ExecutedRoutedEventArgs e)
{
    var cmdParam = e.Paramater as ExpectedType
    if (cmdParam != null)
        //DoStuff...
}

答案 2 :(得分:0)

我意识到我在事实之后回答了很多,但是我遇到了同样的问题,以前的回答似乎使绑定到多个不同的命令变得困难。我到达的解决方案与MatrixManAtYrService的解决方案非常相似,并且分为三个部分:

1)使用ItemContainerStyle属性将命令绑定到ViewModel中的命令-这与前面的答案相同。一个例外是我将CommandParameter绑定到MenuItem。

<Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource Self}}"/>

2)创建一个自定义类,以定义每个MenuItem的外观和行为。菜单的ItemsSource将设置为这些列表。这与其他答案相同。但是,在我的实现中,我给了类一个在调用MenuItemCommand时要执行的Action。我还包含一个布尔值,该布尔值将允许禁用MenuItem。

public class MenuAction
{
    public string Name { get => name; set => name = value; }
    public Action Action { get => action; set => action = value; }
    public bool CanExecute { get => canExecute; set => canExecute = value; }
}

3)在命令实现中,将控制路由到MenuAction中的委托。

public void HandleCommand(object sender)
{
    MenuItem clickedMenuItem = sender as MenuItem;
    MenuAction menuAction = clickedMenuItem?.DataContext as MenuAction;
    if(menuAction != null)
        menuAction.Action();
}

public bool CanMenuItemExecute(object sender)
{
    MenuItem clickedMenuItem = sender as MenuItem;
    MenuAction menuAction = clickedMenuItem?.DataContext as MenuAction;
    if (menuAction != null)
        return menuAction.CanExecute;
    else
        return false;
}

这应该允许您在列表中定义命令的所有行为。从技术上讲,它绑定到单个命令,但在功能上类似于具有多个不同的命令。嵌套的MenuItems和HierarchicalDataTemplates也可以通过一些调整来使用相同的方法。