【问题标题】:How to bind a WPF ListView with contextMenu to viewModel如何将带有 contextMenu 的 WPF ListView 绑定到 viewModel
【发布时间】:2014-09-11 02:01:58
【问题描述】:

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

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

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

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

视图模型

   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>

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

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

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

谢谢

【问题讨论】:

  • XAML 设计者经常就错误对我撒谎。我通常通过在运行时查看输出窗口来验证我的绑定。关于您的命令绑定,我也遇到了命令绑定未触发的问题。结果,我勉强只写了代码隐藏来处理点击事件,并在时间允许的情况下为以后的重构机会做笔记。
  • 尝试使用视图模型构造函数中的相应委托分配来初始化您的中继命令。
  • 感谢您的 cmets,是的,关于问题 1,我觉得我被骗了

标签: c# wpf xaml mvvm


【解决方案1】:

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

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

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}" />

【讨论】:

    【解决方案2】:

    问题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 打败了我。另见this question

    【讨论】:

      【解决方案3】:
       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);
        }
      

      }

      【讨论】:

        猜你喜欢
        • 2020-07-12
        • 1970-01-01
        • 2011-06-22
        • 1970-01-01
        • 2019-11-09
        • 2021-09-23
        • 1970-01-01
        • 1970-01-01
        • 2011-04-04
        相关资源
        最近更新 更多