将命令绑定到视图模型与 ItemsSource from a StaticResource
本文关键字:ItemsSource from StaticResource 模型 命令 绑定 视图 | 更新日期: 2023-09-27 18:36:57
我正在尝试向MenuItem
添加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}"
如果有人能告诉我如何使用这个ItemsSource,同时仍然将我的命令绑定到我的ViewModel,我将不胜感激。我想我可以将命令放在我的团队模型中,但如果可能的话,我想避免这种情况。
编辑:为了澄清我的问题,在 ItemsSource 就位的情况下,ViewModel 中的命令根本不会触发。如果没有 ItemsSource,该命令将触发。我希望能够拥有项目源并且仍然能够触发命令。
编辑:
public class GameContainer
{
static GameContainer()
{
Teams = new ObservableCollection<Team>();
}
public static ObservableCollection<Team> Teams { get; set; }
}
在 App.xaml 中:
<data:GameContainer x:Key="Container" />
集合在程序启动时填充。
一旦我完成这项工作,我的目标是将所选团队传递给视图模型,希望通过 CommandParameter,并显示有关所选团队的信息。
编辑:我在原始帖子中弄错了。来自视图模型的绑定集合也不起作用。
MenuItem
的行为,具有子MenuItem
的项目不会触发Command
,也不应该,因为它没有意义。但是,如果您仍然想在父项单击时触发命令,则有两个选项
您可以使用菜单项上的交互性触发器来调用鼠标按下事件上的命令,例如
<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>
您可以为命令定义附加属性并定义菜单项鼠标向下行为,例如
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 local:MouseCommandBehavior.MouseDownCommand="{Binding OpenTeamPage}"
DisplayMemberPath="Name"
Header="Teams"
ItemsSource="{Binding Teams,
Source={StaticResource Container}}">
如果MenuItem
不是叶节点,则不会执行其命令。只有作为叶子的菜单项(没有子项)才会执行命令。
这可能是由于约定 - 当您单击具有子项的项目时,您会立即显示子项,否则从鼠标悬停到显示子项会有延迟。
尽管(从UX的角度来看)对父级使用命令可能是一个坏主意,但有可能:
<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>
根据您的设计,您可能需要将按钮样式设置为透明。