如何将带有 contextMenu 的 WPF ListView 绑定到 viewModel

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25777880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:30:56  来源:igfitidea点击:

How to bind a WPF ListView with contextMenu to viewModel

c#wpfxamlmvvm

提问by TheGeneral

I'm trying to bind a listview to List<OrderPaymentVm> OrderPaymentswith a right click contextmenu to get the PaymentTransactionId.

我正在尝试List<OrderPaymentVm> OrderPayments使用右键单击上下文菜单将列表视图绑定到PaymentTransactionId.

I have the following property in my forms view model

我的表单视图模型中有以下属性

  public List<OrderPaymentVm> OrderPayments
  {
     get
     {
        return _orderPayments;
     }

     private set
     {
        _orderPayments = value;
        RaisePropertyChanged(() => OrderPayments);
     }
  }

The ViewModel

视图模型

   public class OrderPaymentVm : ViewModelBase
   {

      private RelayCommand _copyPaymentTransactionId;
      public DateTime PaymentTime { get; set; }
      public PaymentType PaymentType { get; set; }
      public string Explanation { get; set; }
      public string PaymentTransactionId { get; set; }
      public decimal Amount { get; set; }
      public RelayCommand CopyPaymentTransactionId
      {
         get { return _copyPaymentTransactionId ?? (_copyPaymentTransactionId = new RelayCommand(ExecuteCopyPaymentTransactionId)); }
      }

      private void ExecuteCopyPaymentTransactionId()
      {
         Clipboard.SetText(string.IsNullOrWhiteSpace(PaymentTransactionId) ? string.Empty : PaymentTransactionId);
      }

   }

I have the following xaml

我有以下 xaml

<ListView Grid.Row="1" ItemsSource="{Binding OrderPayments}" HorizontalAlignment="Stretch" Margin="0,0,0,1">
      <ListView.ContextMenu>
         <ContextMenu>
            <MenuItem Header="Copy Transaction Id"
                  Command="{Binding CopyPaymentTransactionId}"
                  CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}" />
         </ContextMenu>
      </ListView.ContextMenu>
      <ListView.View>
         <GridView>
            <GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Header="Transaction Id" Width="150" DisplayMemberBinding="{Binding PaymentTransactionId}" />
            <GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Header="Time" Width="150" DisplayMemberBinding="{Binding PaymentTime}" />
            <GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Header="Payment Type" Width="100" DisplayMemberBinding="{Binding PaymentType}" />
            <GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Header="Amount" Width="80" DisplayMemberBinding="{Binding Amount, StringFormat='{}{0:C}'}" />
            <GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Header="Explanation" Width="280" DisplayMemberBinding="{Binding Explanation}" />
         </GridView>
      </ListView.View>
</ListView>

Problem 1the xaml designer says there is a problem with the GridViewColumn bindings, it underlines them and says it cannot resolve property, however it compiles and works fine

问题 1xaml 设计者说 GridViewColumn 绑定有问题,它在它们下划线并说它无法解析属性,但是它编译并且工作正常

Problem 2The ConextMenu Command is not hitting the viewmodel command RelayCommand CopyPaymentTransactionId

问题 2ConnextMenu 命令没有命中 viewmodel 命令RelayCommand CopyPaymentTransactionId

Im sure these are simple issues however im spinning my wheels, does any one have any suggestions?

我确定这些都是简单的问题,但是我正在转动我的轮子,有人有什么建议吗?

Thanks

谢谢

回答by pushpraj

here is solution for the 2nd problem. as the context menu is hosted in a popup, which does not inherit the data context from it's parent as it is a separate root element. so you may not simply bind to the parent element's view model.

这是第二个问题的解决方案。因为上下文菜单托管在弹出窗口中,它不会从其父级继承数据上下文,因为它是一个单独的根元素。所以你不能简单地绑定到父元素的视图模型。

here is example to bind the command in a context menu

这是在上下文菜单中绑定命令的示例

Command="{Binding PlacementTarget.SelectedItem.CopyPaymentTransactionId,
                  RelativeSource={RelativeSource AncestorType=ContextMenu}}"

similar to command parameter, you need to specify the source for the command binding.

与命令参数类似,您需要指定命令绑定的来源。

to simplify you may also write the same as

为简化起见,您也可以编写与

<MenuItem Header="Copy Transaction Id"
          DataContext="{Binding PlacementTarget.SelectedItem, 
                                RelativeSource={RelativeSource AncestorType=ContextMenu}}"
          Command="{Binding CopyPaymentTransactionId}"
          CommandParameter="{Binding}" />

回答by nakiya

Problem 1: This is because the designer does not know what the type of objects are in the GridView. You know this, so you can do something like this:

问题 1:这是因为设计者不知道GridView. 你知道这一点,所以你可以做这样的事情:

<Window ... blah blah blah
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    blah blah...

And in ListView:

并在ListView

<ListView blah blah
    d:DataContext="{d:DesignInstance whatevernamespace:WhateverVMYouUse}...

Usually explicitly creating DesignInstance data contexts like this give you better auto complete and removes the superfluous errors that show up in designer.

通常像这样显式地创建 DesignInstance 数据上下文可以让您更好地自动完成并删除设计器中显示的多余错误。

Problem 2: Pushpraj beat me to it. also see this question

问题 2:Pushpraj 打败了我。也看到这个问题

回答by Scott Nimrod

 public class OrderPaymentVm : ViewModelBase
 {

  public OrderPaymentVm ()
  {
     CopyPaymentTransactionId = new RelayCommand(ExecuteCopyPaymentTransactionId));
  }

.
.
.

  public RelayCommand CopyPaymentTransactionId
  {
     get; set;
  }

  private void ExecuteCopyPaymentTransactionId()
  {
     Clipboard.SetText(string.IsNullOrWhiteSpace(PaymentTransactionId) ? string.Empty : PaymentTransactionId);
  }

}

}