3

我正在尝试添加一个ItemsSourceMenuItem同时保持命令绑定到我的 ViewModel(我的窗口的 DataContext)。到目前为止,我还没有想出让它工作的方法。在添加 ItemsSource 之前,绑定很好。我试图绑定的集合来自StaticResource. 有人可以帮我解决这个问题吗?

<MenuItem Command="{Binding OpenTeamPage}"
          DisplayMemberPath="Name"
          Header="Teams"
          ItemsSource="{Binding Teams,
                                Source={StaticResource Container}}" />

我尝试过使用它及其变体,但没有成功:

Command="{Binding OpenTeamPage,
                  RelativeSource={RelativeSource AncestorType=Window},
                  Mode=Default}"

如果有人能告诉我如何在将我的命令绑定到我的 ViewModel 的同时使用此 ItemsSource,我将不胜感激。我想我可以将命令放在我的团队模型中,但如果可能的话,我想避免这种情况。

编辑:为了澄清我的问题,在 ItemsSource 到位后,ViewModel 中的命令根本不会触发。如果没有 ItemsSource,该命令将触发。我希望能够拥有 ItemsSource 并且仍然能够触发命令。

编辑:

public class GameContainer
{
    static GameContainer()
    {
        Teams = new ObservableCollection<Team>();
    }

    public static ObservableCollection<Team> Teams { get; set; } 
}

在 App.xaml 中:

<data:GameContainer x:Key="Container" />

该集合在程序启动时填充。

一旦我完成这项工作,我的目标是将所选团队传递给 Viewmodel,希望通过 CommandParameter,并显示有关所选团队的信息。

编辑:我在原来的帖子中弄错了。来自 Viewmodel 的绑定集合也不起作用。

4

2 回答 2

2

这是MenuItem具有 Child 的 ItemMenuItem不会触发的行为,也不Command应该触发,因为它没有任何意义。但是,如果您仍想在父项单击时触发命令,则有两个选项

  1. 您可以在 MenuItem 上使用交互触发器来调用 MouseDown 事件上的命令,例如

    <MenuItem 
          DisplayMemberPath="Name"
          Header="Teams"
          ItemsSource="{Binding Teams,
                                Source={StaticResource Container}}">
      <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseDown">
            <cmd:EventToCommand Command="{Binding OpenTeamPage}" />
        </i:EventTrigger>
      </i:Interaction.Triggers>
    </MenuItem>
    
  2. 您可以为命令定义一个附加属性并定义 MenuItem MouseDown 行为,例如

     public static class MouseCommandBehavior
     {
    
          public static readonly DependencyProperty MouseDownCommandProperty =
                        DependencyProperty.RegisterAttached("MouseDownCommand",
                        typeof(ICommand),
                        typeof(MouseCommandBehavior),
                        new FrameworkPropertyMetadata(null, (obj, e) => OnMouseCommandChanged(obj, (ICommand)e.NewValue, false)));
    
     public static ICommand GetMouseDownCommand(DependencyObject d)
     {
             return (ICommand)d.GetValue(MouseDownCommandProperty);
     }
    
      public static void SetMouseDownCommand(DependencyObject d, ICommand value)
     {
         d.SetValue(MouseDownCommandProperty, value);
     }
    
     private static void OnMouseCommandChanged(DependencyObject d, ICommand command)
     {
           if (command == null) return;
    
            var element = (FrameworkElement)d;
    
            element.PreviewMouseDown += (obj, e) => command.Execute(null);
      }
     }
    }
    

您可以在 menuItem 上设置此属性值

<MenuItem local:MouseCommandBehavior.MouseDownCommand="{Binding OpenTeamPage}"
      DisplayMemberPath="Name"
      Header="Teams"
      ItemsSource="{Binding Teams,
      Source={StaticResource Container}}">
于 2013-10-25T19:13:07.803 回答
0

MenuItem如果它不是叶节点,则不会执行它的命令。只有作为叶子的菜单项(没有子项的项)正在执行命令。

这可能是由于惯例造成的 - 当您单击具有子项的项目时,您会立即显示子项,否则从鼠标悬停到显示子项会有延迟。

尽管(从用户体验的角度来看)对父级进行命令可能是一个坏主意,但有可能:

<MenuItem DisplayMemberPath="Name"
          Header="{Binding OpenTeamPage}"
          ItemsSource="{Binding Teams, Source={StaticResource Container}}" >
    <MenuItem.HeaderTemplate>
        <DataTemplate>
            <!--Probably need to make this button transparent-->
            <Button Content="Teams"
                    Command="{Binding }"/>
        </DataTemplate>
    </MenuItem.HeaderTemplate>
    <!--This style is for the children to fire the same command as the parent-->
    <MenuItem.ItemContainerStyle>
        <Style TargetType="{x:Type MenuItem}">
            <Setter Property="Command"
                    Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MenuItem}}, Path=Header}"/>
        </Style>
    </MenuItem.ItemContainerStyle>
</MenuItem>

根据您的设计,您可能需要将按钮设置为透明的。

于 2013-10-25T18:43:18.113 回答