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

本文关键字:ListView WPF 绑定 viewModel contextMenu | 更新日期: 2023-09-27 18:21:31

我正在尝试将列表视图绑定到List<OrderPaymentVm> OrderPayments用鼠标右键点击上下文菜单以获得CCD_ 2。

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

  public List<OrderPaymentVm> OrderPayments
  {
     get
     {
        return _orderPayments;
     }
     private set
     {
        _orderPayments = value;
        RaisePropertyChanged(() => OrderPayments);
     }
  }

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);
      }
   }

我有以下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>

问题1xaml设计器说GridViewColumn绑定有问题,它给它们加了下划线,并说它无法解析属性,但它编译并运行良好的

问题2ConextMenu命令未命中viewmodel命令RelayCommand CopyPaymentTransactionId

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

感谢

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

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

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

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

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

为了简化,你也可以写与相同的

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

问题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...

并且在ListView:中

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

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

问题2:Pushpraj打败了我。另请参阅这个问题

 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);
  }

}