【问题标题】:Databinding a command to Context Menu with an Observable Collection使用可观察集合将命令数据绑定到上下文菜单
【发布时间】:2014-09-12 14:23:54
【问题描述】:

我有一个带有一些选项的上下文菜单。其中一个选项是 Observable 集合,我在将视图模型中的命令绑定到它们时遇到问题。我已经看到了许多不同的方法来解决这个问题,但没有一个有效,因为它们与我的问题没有具体关系。这是我的代码:

XAML:

 <ListView ItemsSource="{Binding ListViewItems}" SelectionMode="Single">
            <ListView.ContextMenu>
                <ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
                    <MenuItem Header="Test" Command="{Binding TestCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}" />
                    <Separator></Separator>
                    <MenuItem Header="Status" ItemsSource="{Binding DataContext.ObservableCollectionList}" DisplayMemberPath="Name" Command="{Binding Path=DataContext.UpdateCommand}" CommandParameter="{Binding Path=SelectedItem}"/>
                </ContextMenu>
            </ListView.ContextMenu>
//listviewstuff here
</ListView>

虚拟机:

public class VM : ViewModelBase
{
    public RelayCommand UpdateCommand { get; private set; }
    public Action UpdateCommandAction { get; set; }
    public ObservableCollection<Status> ObservableCollectionList { get; set; }

    public VM()
    {
        this.UpdateCommand = new RelayCommand(new Action(() => this.UpdateCommandAction.DynamicInvoke())));
    }
}

XAML 视图的代码隐藏:

public partial class View
{
    public View()
    {
        InitializeComponent();
        var ViewDataContext = this.DataContext as VM;
        ViewDataContext .UpdateCommandAction = UpdateStatus;
    }


    private void UpdateStatus()
    {
        MessageBox.Show("test");
    }

}

我插入了一个断点,它甚至没有进入方法调用。当我运行程序时,调试输出也没有显示错误。我不明白的是,当我将此命令添加到未由数据绑定列表填充的常规菜单项时,它工作正常。我希望能有一双新的眼睛,并对其工作原理有所了解。

【问题讨论】:

  • (你的视图模型中真的有一个名为DataContext的属性吗?如果是这样,那真的很混乱,我会避免它)

标签: wpf xaml mvvm data-binding mvvm-light


【解决方案1】:

您需要将命令绑定到所有子项,现在您将其绑定到父项上,父项将忽略它,因为它有子项(改为打开子菜单)。

要将其绑定到您需要ItemContainerStyle 的孩子上,请在此处为Command 创建一个Setter。您将需要再次向上走,可能是这样的:{Binding DataContext.DataContext.UpdateCommand, RelativeSource={RelativeSource AncestorType=MenuItem}}(不确定AncestorLevel,如果它确实选择自己而不是父级增加它;加倍DataContext,因为您绑定到DataContext.ObservableCollectionList,假设绑定实际工作)。

同样,菜单中没有SelectedItem,您需要另一个Setter 来代替CommandParameter,它只会绑定到当前项目,即{Binding}


编辑:代码示例:

<MenuItem Header="Status"
          ItemsSource="{Binding DataContext.ObservableCollectionList}"
          DisplayMemberPath="Name">
  <MenuItem.ItemContainerStyle>
    <Style TargetType="MenuItem">
      <Setter Property="Command" Value="{Binding DataContext.DataContext.UpdateCommand,
                                             RelativeSource={RelativeSource AncestorType=MenuItem}}"/>
      <Setter Property="CommandParameter" Value="{Binding}"/>
    </Style>
  </MenuItem.ItemContainerStyle>
</MenuItem>

【讨论】:

  • 谢谢,您的解决方案有效。不幸的是,我刚刚意识到我犯了一个错误。我跟你说的不是100%准确。上下文菜单对于列表视图中的每个项目都应该是唯一的。因此,如果我右键单击第 2 行,这些选项应该会影响该行并且不适用于整个列表视图。此代码是否仍然有效,还是我需要对上述代码进行更改?
  • @user1296981:这主要取决于您的命令在何处以及如何实现。您可以有一个命令,然后您需要同时传递行项目和您拥有的任何参数,或者您将命令作为项目的一部分实现,然后您只需要相对于列表项绑定(因为您已经通过将菜单的DataContext 设置为PlacementTarget),该命令应该只与相应的项目进行交互。
  • 这个想法是列表视图有用户。我右键单击一个用户,我可以改变他们的状态。我对此很陌生,所以我可能只是构建了这个错误。但想法是右键单击“忙碌”用户并将其状态设置为上下文子菜单中的选项之一,例如..“可用”。我需要获取用户 ID 和状态 ID 并将它们传递给方法以在数据库中更新它们并更改应用程序中的属性。
  • @user1296981:那么您的用户虚拟机只需将 ID 存储在字段/属性中,然后在构造函数中直接实现您的状态更改命令,有点像这样:new RelayCommand(param =&gt; UpdateStatus(ID, (Status)param))param 应该成为传递的CommandParameterID 只是VM 中保存用户ID 的属性。
  • 嗯,用户 ID 不是静态变量。它位于用户列表视图中,因此当我右键单击时,我需要与从中选择状态的上下文菜单关联的用户 ID。
【解决方案2】:

您需要List&lt;MenuItem&gt; MenuItems 才能与 ContextMenu ItemSource 属性绑定

public class MenuItem
{
    public string Header { get; set; }

    public ICommand Command { get; set; }
}

XAML: 并设置 itemContainerstyle

<ContextMenu ItemsSource="{Binding MenuItems}" >
        <ContextMenu.ItemContainerStyle>
            <Style TargetType="{x:Type MenuItem}" >
                <Setter Property="Header" Value="{Binding Header}"/>
                <Setter Property="Command" Value="{Binding Command}" />
            </Style>
        </ContextMenu.ItemContainerStyle>
    </ContextMenu>

并根据需要在 ViewModel 中添加任意数量的上下文菜单项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 2016-12-15
    • 2011-06-15
    相关资源
    最近更新 更多