使用StaticResource中的ItemsSource将命令绑定到Viewmodel

时间:2013-10-25 17:50:29

标签: c# wpf xaml mvvm itemssource

我正在尝试将ItemsSource添加到MenuItem,同时将Command绑定到我的ViewModel(我的Window的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}"

如果有人在将我的Command绑定到我的ViewModel时可以告诉我如何使用这个ItemsSource,我将非常感激。我想我可以把Command放在我的Team模型中,但如果可能的话我想避免使用它。

编辑:为了澄清我的问题,使用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的绑定集合也不起作用。

2 个答案:

答案 0 :(得分:2)

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

  1. 您可以在MenuItem上使用Interactivity Triggers在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);
      }
     }
    }
    
  3. 您可以在menuItem上设置此属性值

    <MenuItem local:MouseCommandBehavior.MouseDownCommand="{Binding OpenTeamPage}"
          DisplayMemberPath="Name"
          Header="Teams"
          ItemsSource="{Binding Teams,
          Source={StaticResource Container}}">
    

答案 1 :(得分: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>

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